Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-pw-atm.c
blobcc5721843f479e25c5ef3e826dfc606faadf5999
1 /* packet-pw-atm.c
2 * Routines for ATM PW dissection: it should be conform to RFC 4717.
4 * Copyright 2009 _FF_, _ATA_
6 * Francesco Fondelli <francesco dot fondelli, gmail dot com>
7 * Artem Tamazov <artem [dot] tamazov [at] tellabs [dot] com>
9 * Wireshark - Network traffic analyzer
10 * By Gerald Combs <gerald@wireshark.org>
11 * Copyright 1998 Gerald Combs
13 * SPDX-License-Identifier: GPL-2.0-or-later
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
25 #include "config.h"
27 #include <epan/packet.h>
28 #include <epan/expert.h>
29 #include <epan/prefs.h>
30 #include <epan/tfs.h>
32 #include <wsutil/array.h>
33 #include <wsutil/str_util.h>
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"
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);
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;
55 static int ett_encaps;
56 static int ett_cw;
57 static int ett_cell_header;
58 static int ett_cell;
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;
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;
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;
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;
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;
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;
129 typedef enum {
130 PWATM_SUBMODE_DEFAULT = 0
131 ,PWATM_SUBMODE_ADMIN_CELL /*used in aal5_sdu dissector only*/
132 } pwatm_submode_t;
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 {
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.
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 {
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
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;
178 #define PWATM_PRIVATE_DATA_T_INITIALIZER { \
179 0, PWC_PACKET_PROPERTIES_T_INITIALIZER, 0 \
180 ,PWATM_MODE_UNKNOWN, PWATM_SUBMODE_DEFAULT \
181 ,{-1, -1, -1, -1 } \
182 ,-1, -1, -1 \
183 ,{-1, -1, -1, -1, -1, -1 } \
184 ,false, false, \
187 #define PTI_IS_ADMIN(pti) ((pti) == 4 || (pti) == 5 || (pti) == 6) /*see atm_pt_vals[]*/
189 #define MODE_11(mode) (PWATM_MODE_11_VCC == (mode) || PWATM_MODE_11_VPC == (mode))
190 #define MODE_N1(mode) (PWATM_MODE_N1_NOCW == (mode)|| PWATM_MODE_N1_CW == (mode))
191 #define MODE_11_OR_AAL5_PDU(mode) (MODE_11(mode) || PWATM_MODE_AAL5_PDU == (mode))
193 #define VALUE_SELECTOR_VPC_VCC_PDU(mode,val_vpc,val_vcc,val_pdu)\
194 ((PWATM_MODE_11_VPC == (mode)) \
195 ? (val_vpc) \
196 : ((PWATM_MODE_11_VCC == (mode)) \
197 ? (val_vcc) \
198 : ((PWATM_MODE_AAL5_PDU == (mode)) \
199 ? (val_pdu) \
200 : 0 \
205 #define UPDATE_CUMULATIVE_VALUE(cumulative_val,new_val)\
208 if (-2 >= (cumulative_val))\
211 else if (-1 == (cumulative_val))\
213 (cumulative_val) = (new_val);\
215 else if ((new_val) != (cumulative_val))\
217 (cumulative_val) = -2;\
220 while(0)
222 #define SIZEOF_ATM_CELL_PAYLOAD 48
223 #define SIZEOF_N1_PW_CELL_HEADER 4
224 #define SIZEOF_11_VCC_PW_CELL_HEADER 1
225 #define SIZEOF_11_VPC_PW_CELL_HEADER 3
226 #define SIZEOF_N1_PW_CELL (SIZEOF_ATM_CELL_PAYLOAD+SIZEOF_N1_PW_CELL_HEADER)
227 #define SIZEOF_11_VCC_PW_CELL (SIZEOF_ATM_CELL_PAYLOAD+SIZEOF_11_VCC_PW_CELL_HEADER)
228 #define SIZEOF_11_VPC_PW_CELL (SIZEOF_ATM_CELL_PAYLOAD+SIZEOF_11_VPC_PW_CELL_HEADER)
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";
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";
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";
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.
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;
258 static int
259 pw_cell_size(const pwatm_mode_t mode, const pwatm_submode_t submode)
261 switch (mode)
263 case PWATM_MODE_N1_NOCW:
264 case PWATM_MODE_N1_CW:
265 return SIZEOF_N1_PW_CELL;
266 case PWATM_MODE_11_VCC:
267 return SIZEOF_11_VCC_PW_CELL;
268 case PWATM_MODE_11_VPC:
269 return SIZEOF_11_VPC_PW_CELL;
270 case PWATM_MODE_AAL5_PDU:
271 /* AAL5 PDU size is n*48 bytes */
272 return SIZEOF_ATM_CELL_PAYLOAD;
273 case PWATM_MODE_AAL5_SDU:
274 if (PWATM_SUBMODE_ADMIN_CELL == submode)
276 return SIZEOF_N1_PW_CELL; /*n:1 encapsulation is used for admin cells*/
278 else
280 DISSECTOR_ASSERT_NOT_REACHED();
281 return 0;
283 default:
284 DISSECTOR_ASSERT_NOT_REACHED();
285 return 0;
289 static int
290 pw_cell_header_size(const pwatm_mode_t mode, const pwatm_submode_t submode)
292 switch (mode)
294 case PWATM_MODE_N1_NOCW:
295 case PWATM_MODE_N1_CW:
296 return SIZEOF_N1_PW_CELL_HEADER;
297 case PWATM_MODE_11_VCC:
298 return SIZEOF_11_VCC_PW_CELL_HEADER;
299 case PWATM_MODE_11_VPC:
300 return SIZEOF_11_VPC_PW_CELL_HEADER;
301 case PWATM_MODE_AAL5_SDU:
302 if (PWATM_SUBMODE_ADMIN_CELL == submode)
304 return SIZEOF_N1_PW_CELL_HEADER; /*n:1 encapsulation is used for admin cells*/
306 else
308 DISSECTOR_ASSERT_NOT_REACHED();
309 return 0;
311 case PWATM_MODE_AAL5_PDU: /*not applicable*/
312 default:
313 DISSECTOR_ASSERT_NOT_REACHED();
314 return 0;
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)
324 int cells;
326 DISSECTOR_ASSERT(payload_size >= 0);
328 switch (mode)
330 case PWATM_MODE_N1_NOCW:
331 case PWATM_MODE_N1_CW:
332 case PWATM_MODE_11_VCC:
333 case PWATM_MODE_11_VPC:
334 case PWATM_MODE_AAL5_PDU:
335 cells = payload_size / pw_cell_size(mode, submode);
336 *remainder_size = payload_size - (cells * pw_cell_size(mode, submode));
337 return cells;
338 case PWATM_MODE_AAL5_SDU:
339 if (PWATM_SUBMODE_ADMIN_CELL == submode)
341 cells = payload_size / pw_cell_size(mode, submode);
342 if (cells > 1) cells = 1; /*max. 1 admin cell may be present in aal5 sdu mode */
343 *remainder_size = payload_size - (cells * pw_cell_size(mode, submode));
344 return cells;
346 else
348 /*not applicable*/
350 /*fallthrough*/
351 default:
352 *remainder_size = payload_size;
353 DISSECTOR_ASSERT_NOT_REACHED();
354 return 0;
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)
367 if (pd->props & PWC_ANYOF_CW_BAD)
369 col_append_str(pinfo->cinfo, COL_INFO, "CW:Bad");
372 if (pd->props & PWC_PAY_SIZE_BAD)
374 if (pd->props & PWC_ANYOF_CW_BAD)
376 col_append_str(pinfo->cinfo, COL_INFO, ", ");
378 col_append_str(pinfo->cinfo, COL_INFO, "Payload size:Bad, ");
379 col_append_fstr(pinfo->cinfo, COL_INFO, "%d byte%s"
380 ,(int)payload_size
381 ,plurality(payload_size, "", "s"));
384 if (pd->props == 0) /*omit "atm cells" etc if something is wrong*/
386 /* number of cells may be not known */
387 if (cells >=0)
388 col_append_fstr(pinfo->cinfo, COL_INFO, "%d ATM cell%s"
389 ,cells
390 ,plurality(cells, "", "s"));
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
399 if (pd->cumulative.vpi >= 0)
400 col_append_fstr(pinfo->cinfo, COL_INFO, ", VPI:%.4d", pd->cumulative.vpi);
401 if (pd->cumulative.vci >= 0)
402 col_append_fstr(pinfo->cinfo, COL_INFO, ", VCI:%.5d", pd->cumulative.vci);
403 if (pd->cumulative.pti >= 0)
404 col_append_fstr(pinfo->cinfo, COL_INFO, ", PTI:%.1d", pd->cumulative.pti);
405 if (pd->cumulative.clp >= 0)
406 col_append_fstr(pinfo->cinfo, COL_INFO, ", CLP:%.1d", pd->cumulative.clp);
409 if (padding_size != 0)
411 col_append_fstr(pinfo->cinfo, COL_INFO, ", %d padding"
412 ,(int)padding_size);
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)
423 DISSECTOR_ASSERT(NULL != pdata);
424 DISSECTOR_ASSERT(NULL != ph);
426 memset(ph, 0 , sizeof(*ph)); /* it is OK to clear unknown values */
427 ph->flags = 0; /* status flags */
428 ph->aal = aal;
429 ph->type = TRAF_UNKNOWN;
430 ph->subtype = TRAF_ST_UNKNOWN;
431 ph->vpi = (pdata->vpi >= 0) ? pdata->vpi : 0 /*unknown*/;
432 ph->vci = (pdata->vci >= 0) ? pdata->vci : 0 /*unknown*/;
433 ph->aal2_cid = 0; /*not applicable*//* channel id */
434 ph->channel = 0; /*unknown*//* link: 0 for DTE->DCE, 1 for DCE->DTE */
435 ph->cells = 0; /*zero indicates that we do not have trailer info*/
436 /*user-to-user indicator & CPI*/
437 ph->aal5t_u2u = 0; /* all bits unknown except lsb of UU */
438 if (pdata->aal5_sdu_frame_relay_cr_bit)
439 { /* Let's give Frame Relay C/R bit to ATM dissector.*/
440 ph->aal5t_u2u |= (1<<8); /*UU octet is at << 8 in aal5t_u2u*/
442 ph->aal5t_len = 0; /*unknown*//* length of the packet from trailer*/
443 ph->aal5t_chksum = 0; /*unknown*//* checksum for AAL5 packet from trailer */
444 return;
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)
457 int dissected;
458 tvbuff_t * tvb_2;
460 for(dissected = 0, pd->pw_cell_number = 0;
461 payload_size > dissected;
462 ++(pd->pw_cell_number))
464 tvb_2 = tvb_new_subset_remaining(tvb, dissected);
465 dissected += call_dissector_with_data(dh_cell_header, tvb_2, pinfo, tree, pd);
467 tvb_2 = tvb_new_subset_remaining(tvb, dissected);
469 /*dissect as oam for specific vci/pti, just like atm dissector does*/
470 if ((pd->vci >= 0) && (pd->pti >=0))
472 if (atm_is_oam_cell(pd->vci, pd->pti))
474 pd->cell_mode_oam = true;
478 if (pd->cell_mode_oam)
480 struct pw_atm_phdr ph;
481 tvbuff_t* tvb_3;
482 int bytes_to_dissect;
483 /* prepare buffer for old-style dissector */
484 /* oam cell is always 48 bytes, but payload_size maybe too small */
485 if ((payload_size - dissected) >= SIZEOF_ATM_CELL_PAYLOAD)
486 bytes_to_dissect = SIZEOF_ATM_CELL_PAYLOAD;
487 else
488 bytes_to_dissect = (payload_size - dissected);
489 tvb_3 = tvb_new_subset_length_caplen(tvb_2, 0, bytes_to_dissect, -1);
490 /*aal5_sdu: disable filling columns after 1st (valid) oam cell*/
491 if (pd->mode == PWATM_MODE_AAL5_SDU && (pd->pw_cell_number > 0))
492 ph.enable_fill_columns_by_atm_dissector = false;
493 else
494 ph.enable_fill_columns_by_atm_dissector = true;
495 /* prepare atm pseudo header for atm OAM cell decoding */
496 prepare_pseudo_header_atm(&ph.info, pd, AAL_OAMCELL);
498 call_dissector_with_data(dh_atm_oam_cell, tvb_3, pinfo, tree, &ph);
499 dissected += bytes_to_dissect;
501 else
503 dissected += call_dissector(dh_cell, tvb_2, pinfo, tree);
507 if (padding_size != 0)
509 tvb_2 = tvb_new_subset_remaining(tvb, -padding_size);
510 call_dissector(dh_padding, tvb_2, pinfo, tree);
512 return;
516 static bool
517 too_small_packet_or_notpw(tvbuff_t * tvb
518 ,packet_info * pinfo
519 ,proto_tree * tree
520 ,const int proto_handler
521 ,const char * const proto_name_column)
523 int packet_size;
524 packet_size = tvb_reported_length_remaining(tvb, 0);
526 * FIXME
527 * "4" below should be replaced by something like "min_packet_size_this_dissector"
528 * Also call to dissect_try_cw_first_nibble() should be moved before this block
530 if (packet_size < 4) /* 4 is smallest size which may be sensible (for PWACH dissector) */
532 proto_item * item;
533 item = proto_tree_add_item(tree, proto_handler, tvb, 0, -1, ENC_NA);
534 expert_add_info_format(pinfo, item, &ei_pw_packet_size_too_small,
535 "PW packet size (%d) is too small to carry sensible information"
536 ,(int)packet_size);
537 /* represent problems in the Packet List pane */
538 col_set_str(pinfo->cinfo, COL_PROTOCOL, proto_name_column);
539 col_set_str(pinfo->cinfo, COL_INFO, "Malformed: PW packet is too small");
540 return true;
542 if (dissect_try_cw_first_nibble(tvb, pinfo, tree))
544 return true;
546 return false;
551 * NOTE. RFC describes ATM-specific byte in a cumbersome way.
552 * It is a part of CW, but at the same time, it must be repeated
553 * with each cell, _except_ first.
555 * Alternatively, ATM-specific byte may be considered as part of
556 * PW payload (i.e., as part of pw atm cell header), so we can say that
557 * it is being repeated with each cell.
559 * This dissector is written according to the latter consideration.
561 static int
562 dissect_11_or_aal5_pdu(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void* data _U_)
564 const char * proto_name_column;
565 const char * proto_name_tree = NULL;
566 int payload_size;
567 int cells;
568 pwatm_private_data_t pd = PWATM_PRIVATE_DATA_T_INITIALIZER;
570 proto_name_column = &shortname_11_or_aal5_pdu[0];
571 if (too_small_packet_or_notpw(tvb, pinfo, tree, proto_11_or_aal5_pdu, proto_name_column))
573 return 1;
575 pd.packet_size = tvb_reported_length_remaining(tvb, 0);
578 * Guess encapsulation mode according to M & V bits from the 3rd byte of CW.
579 * Also adjust protocol name strings.
582 uint8_t third_byte;
583 third_byte = tvb_get_uint8(tvb, 3);
584 if (0 == (third_byte & 0x80 /*generic_cw.m*/))
585 { /*1:1 modes*/
586 if (0 != (third_byte & 0x40 /*generic_cw.v*/))
588 pd.mode = PWATM_MODE_11_VPC;
589 proto_name_column = &shortname_11_vpc[0];
590 proto_name_tree = &longname_pw_atm_11_vpc[0];
592 else
594 pd.mode = PWATM_MODE_11_VCC;
595 proto_name_column = &shortname_11_vcc[0];
596 proto_name_tree = &longname_pw_atm_11_vcc[0];
599 else
601 pd.mode = PWATM_MODE_AAL5_PDU;
602 proto_name_column = &shortname_aal5_pdu[0];
603 proto_name_tree = &longname_pw_atm_aal5_pdu[0];
608 /* check how "good" is this packet */
609 pd.props = PWC_PACKET_PROPERTIES_T_INITIALIZER;
610 if (0 != (tvb_get_uint8(tvb, 0) & 0xf0 /*bits03*/))
612 pd.props |= PWC_CW_BAD_BITS03;
614 if (0 != (tvb_get_uint8(tvb, 0) & 0x0f /*generic_cw.rsvd*/))
616 pd.props |= PWC_CW_BAD_RSV;
620 * Do not dissect and validate atm-specific byte (3rd byte of CW).
621 * It will be dissected/validated as pw cell header.
625 * Decide about payload length and padding.
627 * Is padding allowed?
628 * eth header length == 14
629 * mpls label length == 4
630 * cw length == 4
631 * min payload length == 48
632 * => 14 + 4 + 4 + 48 == 70
633 * => 70 >= 64
634 * => no padding allowed
636 if (MODE_11(pd.mode))
638 int bad_padding_size;
639 payload_size = pd.packet_size - (PWC_SIZEOF_CW-1);
640 cells = number_of_cells(pd.mode, pd.submode, payload_size, &bad_padding_size);
641 if ((0 == cells) || (0 != bad_padding_size))
643 pd.props |= PWC_PAY_SIZE_BAD;
646 else
647 { /*aal5_pdu mode*/
648 int bad_padding_size;
649 payload_size = pd.packet_size - PWC_SIZEOF_CW;
650 cells = number_of_cells(pd.mode, pd.submode, payload_size, &bad_padding_size);
651 /* at least 1 cell must be present in the packet in this mode*/
652 if ((1 > cells) || (0 != bad_padding_size))
654 pd.props |= PWC_PAY_SIZE_BAD;
656 cells = -1; /*this value not needed anymore, suppress pinting of it*/
659 if (PWATM_MODE_AAL5_PDU == pd.mode)
661 /* sub-dissectors _may_ overwrite columns in aal5_pdu mode */
662 col_set_str(pinfo->cinfo, COL_PROTOCOL, proto_name_column);
663 col_clear(pinfo->cinfo, COL_INFO);
664 col_append_pw_info(pinfo, payload_size, cells, 0, &pd);
668 proto_item* item;
669 item = proto_tree_add_item(tree, proto_11_or_aal5_pdu, tvb, 0, -1, ENC_NA);
670 /*overwrite heading line*/
671 proto_item_set_text(item, proto_name_tree, 0/*-warn gcc 3.4.4*/);
672 pwc_item_append_text_n_items(item, cells, "good ATM cell");
674 proto_tree* tree2;
675 tree2 = proto_item_add_subtree(item, ett_encaps);
677 proto_item* item2;
678 item2 = proto_tree_add_boolean(tree2
679 ,VALUE_SELECTOR_VPC_VCC_PDU(pd.mode
680 ,hf_pw_type_11_vpc
681 ,hf_pw_type_11_vcc
682 ,hf_pw_type_aal5_pdu)
683 ,tvb, 0, 0, true);
684 proto_item_set_generated(item2);
685 if (MODE_11(pd.mode))
687 item2 = proto_tree_add_int(tree2, hf_11_ncells, tvb, 0, 0, cells);
688 proto_item_set_generated(item2);
692 if (pd.props & PWC_PAY_SIZE_BAD)
694 expert_add_info_format(pinfo, item, &ei_pw_payload_size_invalid_error,
695 "PW payload size (%d) must be <> 0 and multiple of %d",
696 (int)payload_size, pw_cell_size(pd.mode, pd.submode));
697 if ((payload_size != 0) && MODE_11(pd.mode))
699 expert_add_info_format(pinfo, item, &ei_cell_broken,
700 "PW ATM cell [%.3d] is broken", (int)cells);
706 tvbuff_t* tvb_2;
707 tvb_2 = tvb_new_subset_length(tvb, 0, PWC_SIZEOF_CW);
708 call_dissector_with_data(dh_control_word, tvb_2, pinfo, tree, &pd);
710 tvb_2 = tvb_new_subset_remaining(tvb, (PWC_SIZEOF_CW-1));
711 if (MODE_11(pd.mode))
713 dissect_payload_and_padding(tvb_2, pinfo, tree, payload_size, 0, &pd);
715 else
716 { /*aal5_pdu mode*/
717 if (payload_size != 0)
719 tvbuff_t* tvb_3;
720 struct atm_phdr ph;
722 tvb_3 = tvb_new_subset_remaining(tvb_2, 1);
723 /* prepare atm pseudo header for atm aal5 decoding */
724 prepare_pseudo_header_atm(&ph, &pd, AAL_5);
725 call_dissector_with_data(dh_atm_untruncated, tvb_3, pinfo, tree, &ph);
730 if (MODE_11(pd.mode))
732 /* overwrite everything written by sub-dissectors in 1:1 modes*/
733 col_set_str(pinfo->cinfo, COL_PROTOCOL, proto_name_column);
734 col_clear(pinfo->cinfo, COL_INFO);
735 col_append_pw_info(pinfo, payload_size, cells, 0, &pd);
738 return tvb_captured_length(tvb);
742 static int
743 dissect_aal5_sdu(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void* data _U_)
745 const char * proto_name_column;
746 int payload_size;
747 int padding_size;
748 int cells;
749 pwatm_private_data_t pd = PWATM_PRIVATE_DATA_T_INITIALIZER;
751 pd.mode = PWATM_MODE_AAL5_SDU;
753 proto_name_column = &shortname_aal5_sdu[0];
754 if (too_small_packet_or_notpw(tvb, pinfo, tree, proto_aal5_sdu, proto_name_column))
756 return 1;
758 pd.packet_size = tvb_reported_length_remaining(tvb, 0);
760 /* check how "good" is this packet */
761 /* also decide payload length from packet size and CW */
762 if (0 != (tvb_get_uint8(tvb, 0) & 0xf0 /*bits03*/))
764 pd.props |= PWC_CW_BAD_BITS03;
767 pd.submode = PWATM_SUBMODE_DEFAULT;
768 if (0 != (tvb_get_uint8(tvb, 0) & 0x08 /*preferred_cw.T*/))
770 pd.submode = PWATM_SUBMODE_ADMIN_CELL;
773 if (! pref_aal5_sdu_extend_cw_length_with_rsvd)
775 if (0 != (tvb_get_uint8(tvb, 1) & 0xc0 /*preferred_cw.rsvd*/))
777 pd.props |= PWC_CW_BAD_RSV;
781 /* RFC4717:
782 * [ If the packet's length (defined as the length of the layer 2 payload
783 * plus the length of the control word) is less than 64 bytes, the
784 * length field MUST be set to the packet's length. Otherwise, the
785 * length field MUST be set to zero... Note that the length field
786 * is not used in the N-to-one mode and MUST be set to 0. ]
788 * Also we allow some "extensions"conducted by pref_xxx.
790 int payload_size_from_packet;
791 int cw_len; /*length field from cw*/
793 payload_size_from_packet = pd.packet_size - PWC_SIZEOF_CW;
794 if (pref_aal5_sdu_extend_cw_length_with_rsvd)
796 cw_len = tvb_get_uint8(tvb, 1) & 0xff;
798 else
800 cw_len = tvb_get_uint8(tvb, 1) & 0x3f;
804 * Initial assumptions: no padding,
805 * payload size derived from psn packet size.
807 payload_size = payload_size_from_packet;
808 padding_size = 0;
810 if (0 == cw_len)
812 /*keep initial assumptions*/
814 else if (!pref_aal5_sdu_allow_cw_length_nonzero
815 && (PWATM_SUBMODE_ADMIN_CELL == pd.submode))
818 * The "allow CW.Length != 0" option affects
819 * ATM admin cell submode only, because this submode
820 * is equal to N:1 encapsulation.
821 * CW.Length !=0 is always OK for normal (AAL5 payload) submode.
823 pd.props |= PWC_CW_BAD_LEN_MUST_BE_0;
825 else
827 int payload_size_from_cw;
828 payload_size_from_cw = cw_len - PWC_SIZEOF_CW;
829 if (payload_size_from_cw <= 0)
831 pd.props |= PWC_CW_BAD_PAYLEN_LE_0;
833 else if (payload_size_from_cw > payload_size_from_packet)
835 pd.props |= PWC_CW_BAD_PAYLEN_GT_PACKET;
837 else
840 payload_size = payload_size_from_cw;
841 padding_size = payload_size_from_packet - payload_size_from_cw; /* >=0 */
842 if (padding_size != 0)
845 * Padding is not allowed in ATM admin cell submode only,
846 * because this submode is equal to N:1 encapsulation.
847 * Padding is OK for normal (AAL5 payload) submode.
849 if (PWATM_SUBMODE_ADMIN_CELL == pd.submode)
851 pd.props |= PWC_CW_BAD_PADDING_NE_0;
852 /*restore sizes*/
853 payload_size = payload_size_from_packet;
854 padding_size = 0;
860 if (PWATM_SUBMODE_ADMIN_CELL == pd.submode)
862 int bad_padding_size;
863 cells = number_of_cells(pd.mode, pd.submode, payload_size, &bad_padding_size);
864 /* only one atm admin cell is allowed in the packet in this mode*/
865 if ((1 != cells) || (0 != bad_padding_size))
867 pd.props |= PWC_PAY_SIZE_BAD;
870 else
872 cells = -1; /*unknown*/
873 /* Any size is allowed for AAL5 SDU payload */
877 /* fill columns in Packet List */
878 col_set_str(pinfo->cinfo, COL_PROTOCOL, proto_name_column);
879 if (PWATM_SUBMODE_ADMIN_CELL == pd.submode)
881 col_append_str(pinfo->cinfo, COL_PROTOCOL, ", OAM cell");
884 col_clear(pinfo->cinfo, COL_INFO);
885 col_append_pw_info(pinfo, payload_size, cells, padding_size, &pd);
888 proto_item* item;
889 item = proto_tree_add_item(tree, proto_aal5_sdu, tvb, 0, -1, ENC_NA);
891 proto_tree* tree2;
892 tree2 = proto_item_add_subtree(item, ett_encaps);
894 item = proto_tree_add_boolean(tree2, hf_pw_type_aal5_sdu, tvb, 0, 0, true);
895 proto_item_set_generated(item);
898 if (pd.props & PWC_PAY_SIZE_BAD)
900 DISSECTOR_ASSERT(PWATM_SUBMODE_ADMIN_CELL == pd.submode);
901 expert_add_info_format(pinfo, item, &ei_pw_payload_size_invalid_error,
902 "In ATM admin cell mode,"
903 " PW payload size (%d) must be == %d (exactly 1 admin cell)",
904 (int)payload_size, (int)SIZEOF_N1_PW_CELL);
909 tvbuff_t* tvb_2;
910 tvb_2 = tvb_new_subset_length(tvb, 0, PWC_SIZEOF_CW);
911 call_dissector_with_data(dh_control_word, tvb_2, pinfo, tree, &pd);
913 tvb_2 = tvb_new_subset_remaining(tvb, PWC_SIZEOF_CW);
914 if (PWATM_SUBMODE_ADMIN_CELL == pd.submode)
916 dissect_payload_and_padding(tvb_2, pinfo, tree, payload_size, padding_size, &pd);
918 else /*AAL5 payload*/
920 if (payload_size != 0)
922 tvbuff_t* tvb_3;
923 struct atm_phdr ph;
925 tvb_3 = tvb_new_subset_length(tvb_2, 0, payload_size);
926 /* prepare atm pseudo header for atm aal5 decoding */
927 prepare_pseudo_header_atm(&ph, &pd, AAL_5);
928 call_dissector_with_data(dh_atm_truncated, tvb_3, pinfo, tree, &ph); /* no PAD and trailer */
930 if (padding_size != 0)
932 tvbuff_t* tvb_3;
933 tvb_3 = tvb_new_subset_length_caplen(tvb_2, payload_size, padding_size, -1);
934 call_dissector(dh_padding, tvb_3, pinfo, tree);
938 return tvb_captured_length(tvb);
942 static int
943 dissect_n1_cw(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void* data _U_)
945 const char * proto_name_column;
946 int payload_size;
947 int padding_size;
948 int cells;
949 pwatm_private_data_t pd = PWATM_PRIVATE_DATA_T_INITIALIZER;
951 pd.mode = PWATM_MODE_N1_CW;
953 proto_name_column = &shortname_n1_cw[0];
954 if (too_small_packet_or_notpw(tvb, pinfo, tree, proto_n1_cw, proto_name_column))
956 return 1;
958 pd.packet_size = tvb_reported_length_remaining(tvb, 0);
960 /* check how "good" is this packet */
961 /* also decide payload length from packet size and CW */
962 pd.props = PWC_PACKET_PROPERTIES_T_INITIALIZER;
963 if (0 != (tvb_get_uint8(tvb, 0) & 0xf0 /*bits03*/))
965 pd.props |= PWC_CW_BAD_BITS03;
967 if (0 != (tvb_get_uint8(tvb, 0) & 0x0f /*preferred_cw.flags*/))
969 pd.props |= PWC_CW_BAD_FLAGS;
971 if (! pref_n1_cw_extend_cw_length_with_rsvd)
973 if (0 != (tvb_get_uint8(tvb, 1) & 0xc0 /*preferred_cw.rsvd*/))
975 pd.props |= PWC_CW_BAD_RSV;
979 /* RFC4717:
980 * [ If the packet's length (defined as the length of the layer 2 payload
981 * plus the length of the control word) is less than 64 bytes, the
982 * length field MUST be set to the packet's length. Otherwise, the
983 * length field MUST be set to zero... Note that the length field
984 * is not used in the N-to-one mode and MUST be set to 0. ]
986 * Also we allow some "extensions"conducted by pref_xxx.
988 int payload_size_from_packet;
989 int cw_len; /*length field from cw*/
991 payload_size_from_packet = pd.packet_size - PWC_SIZEOF_CW;
992 if (pref_n1_cw_extend_cw_length_with_rsvd)
994 cw_len = tvb_get_uint8(tvb, 1) & 0xff;
996 else
998 cw_len = tvb_get_uint8(tvb, 1) & 0x3f;
1002 * Initial assumptions: no padding,
1003 * payload size derived from psn packet size.
1005 payload_size = payload_size_from_packet;
1006 padding_size = 0;
1008 if (0 == cw_len)
1010 /*keep initial assumptions*/
1012 else if (!pref_n1_cw_allow_cw_length_nonzero)
1014 pd.props |= PWC_CW_BAD_LEN_MUST_BE_0;
1016 else
1018 int payload_size_from_cw;
1019 payload_size_from_cw = cw_len - PWC_SIZEOF_CW;
1020 if (payload_size_from_cw <= 0)
1022 pd.props |= PWC_CW_BAD_PAYLEN_LE_0;
1024 else if (payload_size_from_cw > payload_size_from_packet)
1026 pd.props |= PWC_CW_BAD_PAYLEN_GT_PACKET;
1028 else
1031 payload_size = payload_size_from_cw;
1032 padding_size = payload_size_from_packet - payload_size_from_cw; /* >=0 */
1033 if (padding_size != 0)
1035 pd.props |= PWC_CW_BAD_PADDING_NE_0;
1036 /*restore sizes*/
1037 payload_size = payload_size_from_packet;
1038 padding_size = 0;
1043 int bad_padding_size;
1044 cells = number_of_cells(pd.mode, pd.submode, payload_size, &bad_padding_size);
1045 if ((0 == cells) || (0 != bad_padding_size))
1047 pd.props |= PWC_PAY_SIZE_BAD;
1053 proto_item* item;
1054 item = proto_tree_add_item(tree, proto_n1_cw, tvb, 0, -1, ENC_NA);
1055 pwc_item_append_text_n_items(item, cells, "good ATM cell");
1057 proto_tree* tree2;
1058 tree2 = proto_item_add_subtree(item, ett_encaps);
1060 proto_item* item2;
1061 item2 = proto_tree_add_boolean(tree2, hf_pw_type_n1_cw, tvb, 0, 0, true);
1062 proto_item_set_generated(item2);
1063 item2 = proto_tree_add_int(tree2, hf_n1_cw_ncells, tvb, 0, 0, cells);
1064 proto_item_set_generated(item2);
1067 if (pd.props & PWC_PAY_SIZE_BAD)
1069 if (payload_size != 0)
1071 expert_add_info_format(pinfo, item, &ei_cell_broken,
1072 "PW ATM cell [%.3d] is broken", (int)cells);
1073 expert_add_info_format(pinfo, item, &ei_pw_payload_size_invalid_note,
1074 "PW payload size (%d) must be <>0 and multiple of %d",
1075 (int)payload_size, (int)SIZEOF_N1_PW_CELL);
1077 else
1079 expert_add_info_format(pinfo, item, &ei_pw_payload_size_invalid_error,
1080 "PW payload size (%d) must be <>0 and multiple of %d",
1081 (int)payload_size, (int)SIZEOF_N1_PW_CELL);
1087 tvbuff_t* tvb_2;
1088 tvb_2 = tvb_new_subset_length(tvb, 0, PWC_SIZEOF_CW);
1089 call_dissector_with_data(dh_control_word, tvb_2, pinfo, tree, &pd);
1091 tvb_2 = tvb_new_subset_remaining(tvb, PWC_SIZEOF_CW);
1092 dissect_payload_and_padding(tvb_2, pinfo, tree, payload_size, padding_size, &pd);
1095 /* fill columns in Packet List */
1096 /* overwrite everything written by sub-dissectors */
1097 col_set_str(pinfo->cinfo, COL_PROTOCOL, proto_name_column);
1099 col_clear(pinfo->cinfo, COL_INFO);
1100 col_append_pw_info(pinfo, payload_size, cells, padding_size, &pd);
1101 return tvb_captured_length(tvb);
1105 static int
1106 dissect_n1_nocw(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void* data _U_)
1108 const char * proto_name_column = &shortname_n1_nocw[0];
1109 int payload_size;
1110 int cells;
1111 pwatm_private_data_t pd = PWATM_PRIVATE_DATA_T_INITIALIZER;
1113 pd.mode = PWATM_MODE_N1_NOCW;
1114 pd.packet_size = tvb_reported_length_remaining(tvb, 0);
1116 /* check how "good" is this packet */
1117 /* also decide payload length from packet size */
1118 pd.props = PWC_PACKET_PROPERTIES_T_INITIALIZER;
1119 payload_size = pd.packet_size;
1121 int bad_padding_size;
1122 cells = number_of_cells(pd.mode, pd.submode, pd.packet_size, &bad_padding_size);
1123 if ((cells == 0) || (bad_padding_size != 0))
1125 pd.props |= PWC_PAY_SIZE_BAD;
1130 proto_item* item;
1131 item = proto_tree_add_item(tree, proto_n1_nocw, tvb, 0, -1, ENC_NA);
1132 pwc_item_append_text_n_items(item, cells, "ATM cell");
1134 proto_tree* tree2;
1135 tree2 = proto_item_add_subtree(item, ett_encaps);
1137 proto_item* item2;
1138 item2 = proto_tree_add_boolean(tree2, hf_pw_type_n1_nocw, tvb, 0, 0, true);
1139 proto_item_set_generated(item2);
1140 item2 = proto_tree_add_int(tree2, hf_n1_nocw_ncells, tvb, 0, 0, cells);
1141 proto_item_set_generated(item2);
1144 if (pd.props & PWC_PAY_SIZE_BAD)
1146 if (payload_size != 0)
1148 expert_add_info_format(pinfo, item, &ei_cell_broken,
1149 "Last PW ATM cell [%.3d] is broken", (int)cells);
1150 expert_add_info_format(pinfo, item, &ei_pw_payload_size_invalid_note,
1151 "PW payload size (%d) must be <>0 and multiple of %d",
1152 (int)payload_size, (int)SIZEOF_N1_PW_CELL);
1154 else
1156 expert_add_info_format(pinfo, item, &ei_pw_payload_size_invalid_error,
1157 "PW payload size (%d) must be <>0 and multiple of %d",
1158 (int)payload_size, (int)SIZEOF_N1_PW_CELL);
1163 dissect_payload_and_padding(tvb, pinfo, tree, payload_size, 0, &pd);
1165 /* fill columns in Packet List */
1166 /* overwrite everything written by sub-dissectors */
1167 col_set_str(pinfo->cinfo, COL_PROTOCOL, proto_name_column);
1169 col_clear(pinfo->cinfo, COL_INFO);
1170 col_append_pw_info(pinfo, payload_size, cells, 0, &pd);
1171 return tvb_captured_length(tvb);
1175 static void
1176 proto_item_append_text_cwb3_fields(proto_item * item, const pwatm_private_data_t * const pd)
1178 if (NULL == item) return;
1179 DISSECTOR_ASSERT(NULL != pd);
1180 if (pd->cwb3.m >= 0)
1181 proto_item_append_text(item, "M:%.1u " , (unsigned)(pd->cwb3.m));
1182 if (pd->cwb3.v >= 0)
1183 proto_item_append_text(item, "V:%.1u " , (unsigned)(pd->cwb3.v));
1184 if (pd->cwb3.rsv >= 0)
1185 proto_item_append_text(item, "RSV:%.1u ", (unsigned)(pd->cwb3.rsv));
1186 if (pd->cwb3.u >= 0)
1187 proto_item_append_text(item, "U:%.1u " , (unsigned)(pd->cwb3.u));
1188 if (pd->cwb3.e >= 0)
1189 proto_item_append_text(item, "EFCI:%.1u ",(unsigned)(pd->cwb3.e));
1190 if (pd->cwb3.clp >= 0)
1191 proto_item_append_text(item, "CLP:%.1u ", (unsigned)(pd->cwb3.clp));
1192 return;
1196 static int
1197 dissect_control_word(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void* data)
1199 pwatm_private_data_t* pd;
1201 /* Reject the packet if data is NULL */
1202 if (data == NULL)
1203 return 0;
1204 pd = (pwatm_private_data_t *)data;
1207 * NB: do not touch columns -- keep info from previous dissector
1211 int size;
1212 size = tvb_reported_length_remaining(tvb, 0);
1213 if (size < PWC_SIZEOF_CW)
1215 proto_item *item;
1216 item = proto_tree_add_item(tree, proto_control_word, tvb, 0, -1, ENC_NA);
1217 expert_add_info_format(pinfo, item, &ei_pw_payload_size_invalid_error,
1218 "Packet (size: %d) is too small to carry MPLS PW Control Word"
1219 ,(int)size);
1220 return tvb_captured_length(tvb);
1225 proto_item* item_top;
1226 proto_tree* tree2;
1227 proto_item* item;
1229 item_top = proto_tree_add_item(tree, proto_control_word, tvb, 0, -1, ENC_NA);
1230 pwc_item_append_cw(item_top, tvb_get_ntohl(tvb, 0), false);
1232 tree2 = proto_item_add_subtree(item_top, ett_cw);
1234 /* bits 0..3 */
1235 item = proto_tree_add_item(tree2, hf_cw_bits03, tvb, 0, 1, ENC_BIG_ENDIAN);
1236 if (pd->props & PWC_CW_BAD_BITS03)
1238 /* add item to tree (and show it) only if its value is wrong*/
1239 expert_add_info(pinfo, item, &ei_cw_bits03);
1241 else
1243 proto_item_set_hidden(item); /* show only in error cases */
1246 /* flags */
1247 if (MODE_N1(pd->mode))
1249 item = proto_tree_add_item(tree2, hf_pref_cw_flags, tvb, 0, 1, ENC_BIG_ENDIAN);
1250 if (pd->props & PWC_CW_BAD_FLAGS)
1252 expert_add_info(pinfo, item, &ei_pref_cw_flags);
1255 if (pd->mode == PWATM_MODE_AAL5_SDU)
1257 proto_tree_add_item(tree2, hf_pref_cw_a5s_t, tvb, 0, 1, ENC_BIG_ENDIAN);
1258 proto_tree_add_item(tree2, hf_pref_cw_a5s_e, tvb, 0, 1, ENC_BIG_ENDIAN);
1259 proto_tree_add_item(tree2, hf_pref_cw_a5s_c, tvb, 0, 1, ENC_BIG_ENDIAN);
1260 proto_tree_add_item(tree2, hf_pref_cw_a5s_u, tvb, 0, 1, ENC_BIG_ENDIAN);
1262 * rfc4717: [When FRF.8.1 Frame Relay/ATM PVC Service Interworking [RFC3916]
1263 * traffic is being transported, the CPCS-UU Least Significant Bit
1264 * (LSB) of the AAL5 CPCS-PDU may contain the Frame Relay C/R bit.
1265 * The ingress router, PE1, SHOULD copy this bit to the U bit of the
1266 * control word. The egress router, PE2, SHOULD copy the U bit to
1267 * the CPCS-UU Least Significant Bit (LSB) of the AAL5 CPCS PDU.]
1269 * Let's remember this bit (and then transfer it to ATM dissector).
1271 pd->aal5_sdu_frame_relay_cr_bit =
1272 (0 == (tvb_get_uint8(tvb, 0) & 0x01 /*preferred_cw.U*/))
1273 ? false : true;
1276 /* reserved bits */
1277 if (MODE_11_OR_AAL5_PDU(pd->mode)
1278 || (MODE_N1(pd->mode) && !pref_n1_cw_extend_cw_length_with_rsvd)
1279 /* for N:1 add RSV only if it is NOT used in length */
1280 || ((pd->mode == PWATM_MODE_AAL5_SDU) && !pref_aal5_sdu_extend_cw_length_with_rsvd)
1281 /* for AAl5 SDU add RSV only if it is NOT used in length */)
1283 if (MODE_11_OR_AAL5_PDU(pd->mode))
1285 item = proto_tree_add_item(tree2
1286 ,hf_generic_cw_rsv, tvb, 0, 1, ENC_BIG_ENDIAN);
1288 else
1289 { /*preferred cw*/
1290 item = proto_tree_add_item(tree2
1291 ,hf_pref_cw_rsv, tvb, 1, 1, ENC_BIG_ENDIAN);
1294 if (pd->props & PWC_CW_BAD_RSV)
1296 expert_add_info(pinfo, item, &ei_cw_bits03);
1298 else
1300 proto_item_set_hidden(item); /*...and show only in error cases */
1304 /* length */
1305 if (MODE_N1(pd->mode)
1306 || (PWATM_MODE_AAL5_SDU == pd->mode))
1309 int hf_len = hf_pref_cw_len;
1310 if (MODE_N1(pd->mode))
1312 if (pref_n1_cw_extend_cw_length_with_rsvd)
1313 hf_len = hf_pref_cw_rsvlen;
1315 else /*PW_MODE_AAL5_SDU*/
1317 if (pref_aal5_sdu_extend_cw_length_with_rsvd)
1318 hf_len = hf_pref_cw_rsvlen;
1320 item = proto_tree_add_item(tree2, hf_len, tvb, 1, 1, ENC_BIG_ENDIAN);
1322 if (pd->props & PWC_CW_BAD_LEN_MUST_BE_0)
1324 expert_add_info_format(pinfo, item, &ei_pref_cw_len,
1325 "Bad Length: must be 0 for this encapsulation");
1327 if (pd->props & PWC_CW_BAD_PAYLEN_LE_0)
1329 expert_add_info_format(pinfo, item, &ei_pref_cw_len,
1330 "Bad Length: too small, must be >= %d",
1331 (int)(PWC_SIZEOF_CW+SIZEOF_N1_PW_CELL));
1333 if (pd->props & PWC_CW_BAD_PAYLEN_GT_PACKET)
1335 expert_add_info_format(pinfo, item, &ei_pref_cw_len,
1336 "Bad Length: must be <= than PSN packet size (%d)",
1337 (int)pd->packet_size);
1339 if (pd->props & PWC_CW_BAD_PADDING_NE_0)
1341 expert_add_info_format(pinfo, item, &ei_pref_cw_len,
1342 "Bad Length: must be == PSN packet size (%d), no padding allowed",
1343 (int)pd->packet_size);
1347 /* sequence number */
1348 proto_tree_add_item(tree2, hf_cw_seq, tvb
1349 ,MODE_11_OR_AAL5_PDU(pd->mode) ? 1 : 2, 2, ENC_BIG_ENDIAN);
1351 /* atm-specific byte */
1352 if (MODE_11(pd->mode))
1354 item = proto_tree_add_item(tree2, hf_gen_cw_atmbyte, tvb, 3, 1, ENC_BIG_ENDIAN);
1355 expert_add_info_format(pinfo, item, &ei_gen_cw_atmbyte,
1356 "ATM-specific byte of CW is fully dissected below as %s%s"
1357 ,(PWATM_MODE_11_VPC == pd->mode) ? "a part of " : ""
1358 ,"PW ATM Cell Header [000]");
1360 * Note: if atm-specific byte contains something wrong
1361 * (e.g. non-zero RSV or inadequate V), CW is not
1362 * marked as "bad".
1366 /*3rd byte of CW*/
1367 if (PWATM_MODE_AAL5_PDU == pd->mode)
1369 tvbuff_t* tvb_2;
1370 tvb_2 = tvb_new_subset_remaining(tvb, (PWC_SIZEOF_CW-1));
1371 call_dissector_with_data(dh_cell_header, tvb_2, pinfo, tree2, pd);
1372 proto_item_append_text(item_top, ", ");
1373 proto_item_append_text_cwb3_fields(item_top, pd);
1377 return tvb_captured_length(tvb);
1382 * This function is also used to dissect 3rd byte of CW in AAL5 PDU mode.
1384 static int
1385 dissect_cell_header(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void * data)
1387 pwatm_private_data_t * pd;
1388 bool is_enough_data;
1389 int dissect_size;
1391 /* Reject the packet if data is NULL */
1392 if (data == NULL)
1393 return 0;
1394 pd = (pwatm_private_data_t *)data;
1396 pd->vpi = pd->vci = pd->pti = -1;
1397 pd->cwb3.clp = pd->cwb3.m = pd->cwb3.v = pd->cwb3.rsv = pd->cwb3.u = pd->cwb3.e = -1;
1399 if (PWATM_MODE_AAL5_PDU == pd->mode)
1401 if (tvb_reported_length_remaining(tvb, 0) < 1)
1403 is_enough_data = false;
1404 dissect_size = 0;
1406 else
1408 is_enough_data = true;
1409 dissect_size = 1;
1412 else
1414 int size;
1415 size = tvb_reported_length_remaining(tvb, 0);
1417 if (size < pw_cell_header_size(pd->mode, pd->submode))
1419 is_enough_data = false;
1420 dissect_size = size;
1422 else
1424 is_enough_data = true;
1425 dissect_size = pw_cell_header_size(pd->mode, pd->submode);
1430 * NB: do not touch columns -- keep info from previous dissector
1433 /* Collect info for upper-level dissectors regardless of
1434 * the presence of the tree
1436 if (is_enough_data)
1438 uint8_t tmp8;
1439 switch (pd->mode)
1441 case PWATM_MODE_AAL5_SDU:
1442 DISSECTOR_ASSERT(pd->submode == PWATM_SUBMODE_ADMIN_CELL);
1443 /*fallthrough for ATM admin cell submode only*/
1444 /* FALL THROUGH */
1445 case PWATM_MODE_N1_CW:
1446 case PWATM_MODE_N1_NOCW:
1447 pd->vpi = (tvb_get_ntohs (tvb, 0) >> 4);
1448 pd->vci = (tvb_get_ntoh24(tvb, 1) >> 4) & 0xffff;
1449 tmp8 = (tvb_get_uint8(tvb, 3));
1450 pd->pti = (tmp8 >> 1) & 0x07;
1451 pd->cwb3.clp = (tmp8 >> 0) & 0x01;
1452 UPDATE_CUMULATIVE_VALUE(pd->cumulative.vpi, pd->vpi);
1453 UPDATE_CUMULATIVE_VALUE(pd->cumulative.vci, pd->vci);
1454 UPDATE_CUMULATIVE_VALUE(pd->cumulative.pti, pd->pti);
1455 UPDATE_CUMULATIVE_VALUE(pd->cumulative.clp, pd->cwb3.clp);
1457 * OAM cell mode is always used for aal5_sdu/admin_cell mode,
1458 * even if pti indicates user cell.
1460 pd->cell_mode_oam =
1461 ((pd->mode == PWATM_MODE_AAL5_SDU) && (pd->submode == PWATM_SUBMODE_ADMIN_CELL))
1462 || PTI_IS_ADMIN(pd->pti);
1463 break;
1464 case PWATM_MODE_11_VPC:
1465 pd->vci = tvb_get_ntohs(tvb, 1);
1466 UPDATE_CUMULATIVE_VALUE(pd->cumulative.vci, pd->vci);
1467 /*fallthrough*/
1468 case PWATM_MODE_11_VCC:
1469 tmp8 = (tvb_get_uint8(tvb, 0));
1470 pd->cwb3.m = (tmp8 >> 7) & 0x1;
1471 pd->cwb3.v = (tmp8 >> 6) & 0x1;
1472 pd->cwb3.rsv = (tmp8 >> 4) & 0x3;
1473 pd->pti = (tmp8 >> 1) & 0x7;
1474 pd->cwb3.clp = (tmp8 >> 0) & 0x1;
1475 UPDATE_CUMULATIVE_VALUE(pd->cumulative.pti, pd->pti);
1476 UPDATE_CUMULATIVE_VALUE(pd->cumulative.clp, pd->cwb3.clp);
1478 * OAM cell mode is possible if packet contains atm cell (m == 0).
1480 pd->cell_mode_oam = PTI_IS_ADMIN(pd->pti) && (pd->cwb3.m == 0);
1481 break;
1482 case PWATM_MODE_AAL5_PDU:
1483 tmp8 = (tvb_get_uint8(tvb, 0));
1484 pd->cwb3.m = (tmp8 >> 7) & 0x1;
1485 pd->cwb3.v = (tmp8 >> 6) & 0x1;
1486 pd->cwb3.rsv = (tmp8 >> 3) & 0x7;
1487 pd->cwb3.u = (tmp8 >> 2) & 0x1;
1488 pd->cwb3.e = (tmp8 >> 1) & 0x1;
1489 pd->cwb3.clp = (tmp8 >> 0) & 0x1;
1490 UPDATE_CUMULATIVE_VALUE(pd->cumulative.clp, pd->cwb3.clp);
1491 break;
1492 default:
1493 DISSECTOR_ASSERT_NOT_REACHED();
1494 break;
1499 proto_item* item;
1501 item = proto_tree_add_item(tree, proto_cell_header, tvb
1503 ,dissect_size
1504 ,ENC_NA);
1505 if (PWATM_MODE_AAL5_PDU == pd->mode)
1507 proto_item_set_text(item, "Third byte of Control Word"); /*overwrite heading line*/
1508 /* cwb3 fileds are appended to CW heading line, not here */
1510 else
1512 proto_item_append_text(item, " [%.3d]", pd->pw_cell_number);
1513 proto_item_append_text(item, ", ");
1514 if (pd->vpi >= 0)
1515 proto_item_append_text(item, "VPI:%.4u ", (unsigned)(pd->vpi));
1516 if (pd->vci >= 0)
1517 proto_item_append_text(item, "VCI:%.5u ", (unsigned)(pd->vci));
1518 if (pd->pti >= 0)
1519 proto_item_append_text(item, "PTI:%.1u ", (unsigned)(pd->pti));
1520 proto_item_append_text_cwb3_fields(item, pd);
1524 proto_tree* tree2;
1525 tree2 = proto_item_add_subtree(item, ett_cell_header);
1526 if (is_enough_data)
1528 proto_item* item2;
1529 if (MODE_N1(pd->mode)
1530 || ((pd->mode == PWATM_MODE_AAL5_SDU) && (pd->submode == PWATM_SUBMODE_ADMIN_CELL)))
1532 proto_tree_add_uint(tree2, hf_cell_h_vpi, tvb, 0, 2, (unsigned)pd->vpi);
1533 proto_tree_add_uint(tree2, hf_cell_h_vci, tvb, 1, 3, (unsigned)pd->vci);
1535 item2 = proto_tree_add_item(tree2, hf_cell_h_pti, tvb, 3, 1, ENC_BIG_ENDIAN);
1536 if (NULL == try_val_to_str(pd->pti, atm_pt_vals))
1538 expert_add_info_format(pinfo, item2, &ei_cell_h_pti_undecoded,
1539 "Unknown value of PTI field (%d) in the ATM cell header",
1540 pd->pti);
1542 else if ((pd->mode == PWATM_MODE_AAL5_SDU) && !PTI_IS_ADMIN(pd->pti))
1544 expert_add_info_format(pinfo, item2, &ei_cell_h_pti_malformed,
1545 "ATM admin cell is transerred;"
1546 " PTI field (%d) should be 4, 5 or 6.",
1547 pd->pti);
1550 proto_tree_add_item(tree2, hf_cell_h_clp, tvb, 3, 1, ENC_BIG_ENDIAN);
1552 else if (MODE_11_OR_AAL5_PDU(pd->mode))
1554 item2 = proto_tree_add_item(tree2, hf_cell_h_m , tvb, 0, 1, ENC_BIG_ENDIAN);
1555 if ((0 != pd->cwb3.m) && MODE_11(pd->mode))
1557 expert_add_info(pinfo, item2, &ei_cell_h_m);
1560 item2 = proto_tree_add_item(tree2, hf_cell_h_v , tvb, 0, 1, ENC_BIG_ENDIAN);
1561 if ((0 == pd->cwb3.v) && (PWATM_MODE_11_VPC == pd->mode))
1563 expert_add_info(pinfo, item2, &ei_cell_h_v_not_zero);
1565 if ((0 != pd->cwb3.v) && (PWATM_MODE_11_VCC == pd->mode))
1567 expert_add_info_format(pinfo, item2, &ei_cell_h_v_not_one,
1568 "1:1 VCC mode:"
1569 " V bit must be 0 to indicate that VCI is absent");
1571 if ((0 != pd->cwb3.v) && (PWATM_MODE_AAL5_PDU == pd->mode))
1573 expert_add_info_format(pinfo, item2, &ei_cell_h_v_not_one,
1574 "AAL5 PDU mode:"
1575 " V bit must be 0 to indicate that VCI is absent");
1578 item2 = proto_tree_add_item(tree2
1579 ,(PWATM_MODE_AAL5_PDU == pd->mode)
1580 ? hf_aal5_pdu_rsv
1581 : hf_cell_h_rsv
1582 ,tvb, 0, 1, ENC_BIG_ENDIAN);
1583 if (0 != pd->cwb3.rsv)
1585 expert_add_info(pinfo, item2, &ei_cell_h_rsv);
1587 else
1589 proto_item_set_hidden(item2); /*...and show only in error cases */
1592 if (MODE_11(pd->mode))
1594 item2 = proto_tree_add_item(tree2, hf_cell_h_pti, tvb, 0, 1, ENC_BIG_ENDIAN);
1595 if (NULL == try_val_to_str(pd->pti, atm_pt_vals))
1597 expert_add_info_format(pinfo, item2, &ei_cell_h_pti_undecoded,
1598 "Unknown value of PTI field (%d) in the atm-specific byte"
1599 ,pd->pti);
1602 else
1604 proto_tree_add_item(tree2, hf_aal5_pdu_u, tvb, 0, 1, ENC_BIG_ENDIAN);
1605 proto_tree_add_item(tree2, hf_aal5_pdu_e, tvb, 0, 1, ENC_BIG_ENDIAN);
1608 proto_tree_add_item(tree2, hf_cell_h_clp, tvb, 0, 1, ENC_BIG_ENDIAN);
1610 if (PWATM_MODE_11_VPC == pd->mode)
1612 proto_tree_add_uint(tree2, hf_cell_h_vci, tvb, 1, 2
1613 ,(unsigned)pd->vci);
1616 else
1618 DISSECTOR_ASSERT_NOT_REACHED();
1621 else
1623 expert_add_info_format(pinfo, item, &ei_pw_payload_size_invalid_error,
1624 "Not enough data (size: %d), impossible to decode",
1625 (int)dissect_size);
1629 return dissect_size;
1634 static int
1635 dissect_cell(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void * data)
1637 bool is_enough_data;
1638 int dissect_size;
1639 int size;
1640 proto_item* item;
1641 pwatm_private_data_t * pd = (pwatm_private_data_t *)data;
1643 size = tvb_reported_length_remaining(tvb, 0);
1644 if (size < SIZEOF_ATM_CELL_PAYLOAD)
1646 is_enough_data = false;
1647 dissect_size = size;
1649 else
1651 is_enough_data = true;
1652 dissect_size = SIZEOF_ATM_CELL_PAYLOAD;
1656 * NB: do not touch columns -- keep info from previous dissector
1659 item = proto_tree_add_item(tree, proto_cell, tvb, 0, dissect_size, ENC_NA);
1660 if (NULL != pd)
1661 proto_item_append_text(item, " [%.3d]", pd->pw_cell_number);
1663 pwc_item_append_text_n_items(item, dissect_size, "byte");
1664 if (!is_enough_data)
1666 expert_add_info_format(pinfo, item, &ei_pw_payload_size_invalid_error,
1667 "Bad length of cell payload: must be == %d",
1668 (int)SIZEOF_ATM_CELL_PAYLOAD);
1672 proto_tree* tree2;
1673 tvbuff_t* tvb_d;
1674 tree2 = proto_item_add_subtree(item, ett_cell);
1675 tvb_d = tvb_new_subset_length_caplen(tvb, 0, dissect_size, -1);
1676 call_data_dissector(tvb_d, pinfo, tree2);
1677 item = proto_tree_add_int(tree2, hf_cell_payload_len, tvb, 0, 0, dissect_size);
1678 proto_item_set_hidden(item);
1681 return dissect_size;
1685 void
1686 proto_register_pw_atm_ata(void)
1688 static const value_string clp_vals[] = {
1689 { 0, "High priority" },
1690 { 1, "Low priority" },
1691 { 0, NULL }
1693 static const value_string m_vals[] = {
1694 { 0, "ATM cell" },
1695 { 1, "AAL5 payload" },
1696 { 0, NULL }
1698 static const value_string u_vals[] = {
1699 { 0, "This frame does not contain the last cell of AAL5 PDU" },
1700 { 1, "This frame contains the last cell of AAL5 PDU" },
1701 { 0, NULL }
1703 static const value_string e_vals[] = {
1704 { 0, "Congestion is not experienced" },
1705 { 1, "Congestion is experienced for one or more ATM AAL5 cells" },
1706 { 0, NULL }
1708 static hf_register_info hfa_cell_header[] = {
1709 { &hf_cell_h_vpi ,{"VPI" ,"atm.vpi"
1710 ,FT_UINT16 ,BASE_DEC ,NULL ,0
1711 ,NULL ,HFILL }},
1713 { &hf_cell_h_vci ,{"VCI" ,"atm.vci"
1714 ,FT_UINT16 ,BASE_DEC ,NULL ,0
1715 ,NULL ,HFILL }},
1717 { &hf_cell_h_pti ,{"Payload Type" ,"atm.pti"
1718 ,FT_UINT8 ,BASE_DEC ,VALS(atm_pt_vals),0x0e
1719 ,"The 3-bit Payload Type Identifier (PTI) incorporates ATM Layer"
1720 " PTI coding of the cell. These bits are set to the value of the"
1721 " PTI of the encapsulated ATM cell."
1722 ,HFILL }},
1724 { &hf_cell_h_clp ,{"Cell Loss Priority" ,"atm.clp"
1725 ,FT_UINT8 ,BASE_DEC ,VALS(clp_vals) ,0x01
1726 ,"The Cell Loss Priority (CLP) field indicates CLP value"
1727 " of the encapsulated cell."
1728 ,HFILL }},
1730 { &hf_cell_h_m ,{"Transport Mode" ,"atm.pw_control_byte.m"
1731 ,FT_UINT8 ,BASE_DEC ,VALS(m_vals) ,0x80
1732 ,"Bit (M) of the control byte indicates whether the packet"
1733 " contains an ATM cell or a frame payload. If set to 0,"
1734 " the packet contains an ATM cell. If set to 1, the PDU"
1735 " contains an AAL5 payload."
1736 ,HFILL }},
1738 { &hf_cell_h_v ,{"VCI Present" ,"atm.pw_control_byte.v"
1739 ,FT_BOOLEAN ,8 ,TFS(&tfs_yes_no),0x40
1740 ,"Bit (V) of the control byte indicates whether the VCI field"
1741 " is present in the packet. If set to 1, the VCI field is present"
1742 " for the cell. If set to 0, no VCI field is present."
1743 ,HFILL }},
1745 { &hf_cell_h_rsv ,{"Reserved bits" ,"atm.pw_control_byte.rsv"
1746 ,FT_UINT8 ,BASE_DEC ,NULL ,0x30
1747 ,"The reserved bits should be set to 0 at the transmitter and"
1748 " ignored upon reception."
1749 ,HFILL }},
1751 { &hf_aal5_pdu_rsv ,{"Reserved bits" ,"atm.pw_control_byte.rsv"
1752 ,FT_UINT8 ,BASE_DEC ,NULL ,0x38
1753 ,"The reserved bits should be set to 0 at the transmitter and"
1754 " ignored upon reception."
1755 ,HFILL }},
1757 { &hf_aal5_pdu_u ,{"U bit" ,"atm.pw_control_byte.u"
1758 ,FT_UINT8 ,BASE_DEC ,VALS(u_vals) ,0x04
1759 ,"Indicates whether this frame contains the last cell of"
1760 " an AAL5 PDU and represents the value of the ATM User-to-User"
1761 " bit for the last ATM cell of the PSN frame. Note: The ATM"
1762 " User-to-User bit is the least significant bit of the PTI"
1763 " in the ATM header."
1764 ,HFILL }},
1766 { &hf_aal5_pdu_e ,{"EFCI" ,"atm.pw_control_byte.efci"
1767 ,FT_UINT8 ,BASE_DEC ,VALS(e_vals) ,0x02
1768 ,"EFCI is set to the EFCI state of the last cell of the"
1769 " AAL5 PDU or AAL5 fragment. Note: The EFCI state is"
1770 " indicated in the middle bit of each ATM cell's PTI."
1771 ,HFILL }}
1773 static hf_register_info hfa_cell[] = {
1774 {&hf_cell_payload_len ,{"Length" ,"atm.cell.len"
1775 ,FT_INT32 ,BASE_DEC ,NULL ,0
1776 ,NULL ,HFILL }}
1779 static hf_register_info hfa_n1_nocw[] = {
1780 { &hf_n1_nocw_ncells,
1781 { "Number of good N:1 no CW encapsulated cells", "pw.atm.n1_nocw.cells", FT_INT32,
1782 BASE_DEC, NULL, 0, NULL, HFILL }},
1783 { &hf_pw_type_n1_nocw,
1784 { "N:1 noCW", "pw.type.atm.n1nocw", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1785 NULL, HFILL }}
1788 static hf_register_info hfa_n1_cw[] = {
1789 { &hf_n1_cw_ncells,
1790 { "Number of good N:1 CW encapsulated cells", "pw.atm.n1_cw.cells", FT_INT32,
1791 BASE_DEC, NULL, 0, NULL, HFILL }},
1792 { &hf_pw_type_n1_cw,
1793 { "N:1 CW", "pw.type.atm.n1cw", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1794 NULL, HFILL }}
1797 static hf_register_info hfa_11_aal5pdu[] = {
1798 { &hf_11_ncells,
1799 { "Number of good 1:1 encapsulated cells", "pw.atm.11.cells", FT_INT32,
1800 BASE_DEC, NULL, 0, NULL, HFILL }},
1801 { &hf_pw_type_11_vcc,
1802 { "1:1 VCC", "pw.type.atm.11vcc", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1803 NULL, HFILL }},
1804 { &hf_pw_type_11_vpc,
1805 { "1:1 VPC", "pw.type.atm.11vpc", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1806 NULL, HFILL }},
1807 { &hf_pw_type_aal5_pdu,
1808 { "AAL5 PDU", "pw.type.atm.aal5pdu", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1809 NULL, HFILL }}
1812 static hf_register_info hfa_aal5_sdu[] = {
1813 { &hf_pw_type_aal5_sdu,
1814 { "AAL5 SDU", "pw.type.atm.aal5sdu", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1815 NULL, HFILL }}
1818 static const value_string a5s_t_vals[] = {
1819 { 0, "AAL5 payload" },
1820 { 1, "ATM admin cell" },
1821 { 0, NULL }
1824 static const value_string a5s_e_vals[] = {
1825 { 0, "No congestion" },
1826 { 1, "Congestion experienced" },
1827 { 0, NULL }
1830 static hf_register_info hfa_cw[] = {
1831 { &hf_cw_bits03 ,{"Bits 0 to 3" ,"pw.cw.bits03"
1832 ,FT_UINT8 ,BASE_HEX ,NULL ,0xf0
1833 ,NULL ,HFILL }},
1835 { &hf_pref_cw_flags ,{"Flags" ,"pw.cw.flags"
1836 ,FT_UINT8 ,BASE_HEX ,NULL ,0x0f
1837 ,NULL ,HFILL }},
1839 { &hf_pref_cw_a5s_t ,{"Payload type" ,"atm.pt"
1840 ,FT_UINT8 ,BASE_DEC ,VALS(a5s_t_vals),0x08
1841 ,"Bit (T) of the control word indicates whether the packet contains"
1842 " an ATM admin cell or an AAL5 payload. If T = 1, the packet"
1843 " contains an ATM admin cell, encapsulated according to the N:1"
1844 " cell relay encapsulation. If not set, the PDU"
1845 " contains an AAL5 payload."
1846 ,HFILL }},
1848 { &hf_pref_cw_a5s_e ,{"EFCI bit" ,"atm.efci"
1849 ,FT_UINT8 ,BASE_DEC ,VALS(a5s_e_vals),0x04
1850 ,"The ingress router sets this bit to 1 if the EFCI bit"
1851 " of the final cell of those that transported the AAL5 CPCS-SDU is"
1852 " set to 1, or if the EFCI bit of the single ATM cell to be"
1853 " transported in the packet is set to 1. Otherwise, this bit"
1854 " is set to 0."
1855 ,HFILL }},
1857 { &hf_pref_cw_a5s_c ,{"CLP bit" ,"atm.clp"
1858 ,FT_UINT8 ,BASE_DEC ,VALS(clp_vals) ,0x02
1859 ,"The ingress router sets this bit to 1 if the CLP bit"
1860 " of any of the ATM cells that transported the AAL5 CPCS-SDU is set"
1861 " to 1, or if the CLP bit of the single ATM cell to be transported"
1862 " in the packet is set to 1. Otherwise this bit is set to 0."
1863 ,HFILL }},
1865 { &hf_pref_cw_a5s_u ,{"U bit (Command/Response)" ,"pw.cw.aal5sdu.u"
1866 ,FT_UINT8 ,BASE_DEC ,NULL ,0x01
1867 ,"When FRF.8.1 Frame Relay/ATM PVC Service Interworking [RFC3916]"
1868 " traffic is being transported, the Least-Significant Bit of CPCS-UU"
1869 " of the AAL5 CPCS-PDU may contain the Frame Relay C/R bit."
1870 " The ingress router copies this bit here."
1871 ,HFILL }},
1873 { &hf_pref_cw_rsv ,{"Reserved bits" ,"pw.cw.rsv"
1874 ,FT_UINT8 ,BASE_DEC ,NULL ,0xc0
1875 ,NULL ,HFILL }},
1877 { &hf_generic_cw_rsv ,{"Reserved bits" ,"pw.cw.rsv"
1878 ,FT_UINT8 ,BASE_DEC ,NULL ,0x0f
1879 ,NULL ,HFILL }},
1881 { &hf_pref_cw_len ,{"Length" ,"pw.cw.length"
1882 ,FT_UINT8 ,BASE_DEC ,NULL ,0x3f
1883 ,NULL ,HFILL }},
1885 { &hf_pref_cw_rsvlen ,{"Length (extended)" ,"pw.cw.length"
1886 ,FT_UINT8 ,BASE_DEC ,NULL ,0x0
1887 ,NULL ,HFILL }},
1889 { &hf_cw_seq ,{"Sequence number" ,"pw.cw.seqno"
1890 ,FT_UINT16 ,BASE_DEC ,NULL ,0
1891 ,NULL ,HFILL }},
1893 { &hf_gen_cw_atmbyte ,{"ATM-specific byte" ,"pw.cw.3rd_byte"
1894 ,FT_UINT8 ,BASE_HEX ,NULL ,0x0
1895 ,NULL ,HFILL }}
1897 static int *ett_array[] = {
1898 &ett_encaps
1899 ,&ett_cw
1900 ,&ett_cell_header
1901 ,&ett_cell
1903 static ei_register_info ei[] = {
1904 { &ei_pw_packet_size_too_small, { "pw.packet_size_too_small", PI_MALFORMED, PI_ERROR, "PW packet size too small", EXPFILL }},
1905 { &ei_pw_payload_size_invalid_error, { "pw.payload.size_invalid", PI_MALFORMED, PI_ERROR, "PW payload size invalid", EXPFILL }},
1906 { &ei_cell_broken, { "atm.cell_broken", PI_MALFORMED, PI_ERROR, "PW ATM cell is broken", EXPFILL }},
1907 { &ei_pw_payload_size_invalid_note, { "pw.payload.size_invalid", PI_MALFORMED, PI_NOTE, "PW payload size invalid", EXPFILL }},
1908 { &ei_cw_bits03, { "pw.cw.bits03.not_zero", PI_MALFORMED, PI_ERROR, "Bits 0..3 of Control Word must be 0", EXPFILL }},
1909 { &ei_pref_cw_flags, { "pw.cw.flags.not_zero", PI_MALFORMED, PI_ERROR, "Flags must be 0 for PW ATM N:1 encapsulation", EXPFILL }},
1910 { &ei_pref_cw_len, { "pw.cw.length.invalid", PI_MALFORMED, PI_ERROR, "Bad Length: must be 0 for this encapsulation", EXPFILL }},
1911 { &ei_cell_h_pti_undecoded, { "atm.pti.invalid", PI_UNDECODED, PI_WARN, "Unknown value of PTI field in the ATM cell header", EXPFILL }},
1912 { &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 }},
1913 { &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 }},
1914 { &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 }},
1915 { &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 }},
1916 { &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 }},
1917 { &ei_gen_cw_atmbyte, { "pw.cw.atmbyte", PI_PROTOCOL, PI_NOTE, "ATM-specific byte of CW is fully dissected below", EXPFILL }},
1920 expert_module_t* expert_cell;
1922 proto_n1_cw =
1923 proto_register_protocol(pwc_longname_pw_atm_n1_cw
1924 ,shortname_n1_cw
1925 ,"mplspwatmn1cw");
1926 proto_11_or_aal5_pdu =
1927 proto_register_protocol(pwc_longname_pw_atm_11_or_aal5_pdu
1928 ,shortname_11_or_aal5_pdu
1929 ,"mplspwatm11_or_aal5pdu");
1930 proto_aal5_sdu =
1931 proto_register_protocol(pwc_longname_pw_atm_aal5_sdu
1932 ,shortname_aal5_sdu
1933 ,"mplspwatmaal5sdu");
1934 proto_n1_nocw =
1935 proto_register_protocol(pwc_longname_pw_atm_n1_nocw
1936 ,shortname_n1_nocw
1937 ,"mplspwatmn1nocw");
1938 proto_control_word =
1939 proto_register_protocol("MPLS PW ATM Control Word"
1940 ,"MPLS PW ATM Control Word"
1941 ,"mplspwatmcontrolword");
1942 proto_cell_header =
1943 proto_register_protocol("MPLS PW ATM Cell Header"
1944 ,"MPLS PW ATM Cell Header"
1945 ,"mplspwatmcellheader");
1946 proto_cell =
1947 proto_register_protocol("ATM Cell"
1948 ,"ATM Cell"
1949 ,"mplspwatmcell");
1951 proto_register_field_array( proto_cell ,hfa_cell ,array_length(hfa_cell));
1952 expert_cell = expert_register_protocol(proto_cell);
1953 expert_register_field_array(expert_cell, ei, array_length(ei));
1955 proto_register_field_array( proto_cell_header ,hfa_cell_header,array_length(hfa_cell_header));
1956 proto_register_field_array( proto_control_word ,hfa_cw ,array_length(hfa_cw));
1957 proto_register_field_array( proto_n1_nocw ,hfa_n1_nocw ,array_length(hfa_n1_nocw));
1958 proto_register_field_array( proto_n1_cw ,hfa_n1_cw ,array_length(hfa_n1_cw));
1959 proto_register_field_array( proto_11_or_aal5_pdu ,hfa_11_aal5pdu ,array_length(hfa_11_aal5pdu));
1960 proto_register_field_array( proto_aal5_sdu ,hfa_aal5_sdu ,array_length(hfa_aal5_sdu));
1962 proto_register_subtree_array(ett_array, array_length(ett_array));
1964 dh_control_word = register_dissector("mpls_pw_atm_control_word" ,dissect_control_word ,proto_control_word);
1965 dh_cell = register_dissector("mpls_pw_atm_cell" ,dissect_cell ,proto_cell);
1966 dh_cell_header = register_dissector("mpls_pw_atm_cell_header",dissect_cell_header ,proto_cell_header);
1967 register_dissector("mpls_pw_atm_aal5_sdu" ,dissect_aal5_sdu ,proto_aal5_sdu);
1968 register_dissector("mpls_pw_atm_11_or_aal5_pdu" ,dissect_11_or_aal5_pdu ,proto_11_or_aal5_pdu);
1969 register_dissector("mpls_pw_atm_n1_cw" ,dissect_n1_cw ,proto_n1_cw);
1970 register_dissector("mpls_pw_atm_n1_nocw" ,dissect_n1_nocw ,proto_n1_nocw);
1972 static const char description_allow_cw_length_nonzero[] =
1973 "Enable to allow non-zero Length in Control Word."
1974 " This may be needed to correctly decode traffic from some legacy devices"
1975 " which generate non-zero Length even if there is no padding in the packet."
1976 " Note that Length should have proper value (dissector checks this anyway)."
1977 "\n\n"
1978 "Disable to blame all packets with CW.Length <> 0. This conforms to RFC4717."
1980 static const char description_extend_cw_length_with_rsvd[] =
1981 "Enable to use reserved bits (8..9) of Control Word as an extension of CW.Length."
1982 " This may be needed to correctly decode traffic from some legacy devices"
1983 " which uses reserved bits as extension of Length"
1984 "\n\n"
1985 "Disable to blame all packets with CW.Reserved <> 0. This conforms to RFC4717."
1987 module_t * module_n1_cw;
1988 module_t * module_aal5_sdu;
1990 module_n1_cw = prefs_register_protocol(proto_n1_cw,NULL);
1991 prefs_register_bool_preference(module_n1_cw
1992 ,"allow_cw_length_nonzero"
1993 ,"Allow CW.Length <> 0"
1994 ,&description_allow_cw_length_nonzero[0]
1995 ,&pref_n1_cw_allow_cw_length_nonzero);
1996 prefs_register_bool_preference(module_n1_cw
1997 ,"extend_cw_length_with_rsvd"
1998 ,"Use CW.Reserved as extension of CW.Length"
1999 ,&description_extend_cw_length_with_rsvd[0]
2000 ,&pref_n1_cw_extend_cw_length_with_rsvd);
2002 module_aal5_sdu = prefs_register_protocol(proto_aal5_sdu,NULL);
2003 prefs_register_bool_preference(module_aal5_sdu
2004 ,"allow_cw_length_nonzero_aal5"
2005 ,"Allow CW.Length <> 0"
2006 ,&description_allow_cw_length_nonzero[0]
2007 ,&pref_aal5_sdu_allow_cw_length_nonzero);
2008 prefs_register_bool_preference(module_aal5_sdu
2009 ,"extend_cw_length_with_rsvd_aal5"
2010 ,"Use CW.Reserved as extension of CW.Length"
2011 ,&description_extend_cw_length_with_rsvd[0]
2012 ,&pref_aal5_sdu_extend_cw_length_with_rsvd);
2017 void
2018 proto_reg_handoff_pw_atm_ata(void)
2020 dissector_handle_t h;
2021 h = find_dissector("mpls_pw_atm_n1_cw");
2022 dissector_add_for_decode_as( "mpls.label", h );
2023 dissector_add_for_decode_as( "mpls.pfn", h);
2024 h = find_dissector("mpls_pw_atm_n1_nocw");
2025 dissector_add_for_decode_as( "mpls.label", h );
2026 dissector_add_for_decode_as( "mpls.pfn", h);
2027 h = find_dissector("mpls_pw_atm_11_or_aal5_pdu");
2028 dissector_add_for_decode_as( "mpls.label", h );
2029 dissector_add_for_decode_as( "mpls.pfn", h);
2030 h = find_dissector("mpls_pw_atm_aal5_sdu");
2031 dissector_add_for_decode_as( "mpls.label", h );
2032 dissector_add_for_decode_as( "mpls.pfn", h);
2034 dh_atm_truncated = find_dissector("atm_pw_truncated");
2035 dh_atm_untruncated = find_dissector("atm_pw_untruncated");
2036 dh_atm_oam_cell = find_dissector("atm_pw_oam_cell");
2037 dh_padding = find_dissector("pw_padding");
2041 * Editor modelines - https://www.wireshark.org/tools/modelines.html
2043 * Local variables:
2044 * c-basic-offset: 8
2045 * tab-width: 8
2046 * indent-tabs-mode: t
2047 * End:
2049 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
2050 * :indentSize=8:tabSize=8:noTabs=false: