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>
11 * Wireshark - Network traffic analyzer
12 * By Gerald Combs <gerald@wireshark.org>
13 * Copyright 1998 Gerald Combs
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
32 - ATM N-to-One Cell Mode (with CW)
33 - ATM N-to-One Cell Mode (no CW)
34 - ATM One-to-One Cell Mode
47 #include <epan/packet.h>
48 #include <epan/expert.h>
49 #include <epan/prefs.h>
51 #include <wiretap/wtap.h> /*for atm pseudo header*/
52 #include "packet-mpls.h"
53 #include "packet-atm.h"
54 #include "packet-pw-atm.h"
55 #include "packet-pw-common.h"
57 static gint proto_n1_nocw = -1;
58 static gint proto_n1_cw = -1;
59 static gint proto_11_or_aal5_pdu = -1;
60 static gint proto_aal5_sdu = -1;
61 /* subordinate dissectors: */
62 static gint proto_control_word = -1;
63 static gint proto_cell_header = -1;
64 static gint proto_cell = -1;
66 static gint ett_encaps = -1;
67 static gint ett_cw = -1;
68 static gint ett_cell_header = -1;
69 static gint ett_cell = -1;
71 static int hf_pw_type_n1_cw = -1;
72 static int hf_pw_type_n1_nocw = -1;
73 static int hf_pw_type_11_vcc = -1;
74 static int hf_pw_type_11_vpc = -1;
75 static int hf_pw_type_aal5_sdu = -1;
76 static int hf_pw_type_aal5_pdu = -1;
78 static int hf_cell_h_vpi = -1;
79 static int hf_cell_h_vci = -1;
80 static int hf_cell_h_pti = -1;
81 static int hf_cell_h_clp = -1;
82 static int hf_cell_h_m = -1;
83 static int hf_cell_h_v = -1;
84 static int hf_cell_h_rsv = -1;
85 static int hf_aal5_pdu_rsv = -1;
86 static int hf_aal5_pdu_u = -1;
87 static int hf_aal5_pdu_e = -1;
89 static int hf_cw_bits03 = -1;
90 static int hf_pref_cw_rsv = -1;
91 static int hf_generic_cw_rsv = -1;
92 static int hf_pref_cw_flags = -1;
93 static int hf_pref_cw_a5s_t = -1;
94 static int hf_pref_cw_a5s_e = -1;
95 static int hf_pref_cw_a5s_c = -1;
96 static int hf_pref_cw_a5s_u = -1;
97 static int hf_pref_cw_len = -1;
98 static int hf_pref_cw_rsvlen = -1;
99 static int hf_cw_seq = -1;
100 static int hf_n1_cw_ncells = -1;
101 static int hf_n1_nocw_ncells = -1;
102 static int hf_11_ncells = -1;
103 static int hf_gen_cw_atmbyte = -1;
104 static int hf_cell_payload_len = -1;
106 static dissector_handle_t dh_cell;
107 static dissector_handle_t dh_cell_header;
108 static dissector_handle_t dh_control_word;
109 static dissector_handle_t dh_atm_truncated;
110 static dissector_handle_t dh_atm_untruncated;
111 static dissector_handle_t dh_atm_oam_cell;
112 static dissector_handle_t dh_padding;
113 static dissector_handle_t dh_data;
115 #define PTI_IS_ADMIN(pti) ((pti) == 4 || (pti) == 5 || (pti) == 6) /*see atm_pt_vals[]*/
117 #define MODE_11(mode) (PWATM_MODE_11_VCC == (mode) || PWATM_MODE_11_VPC == (mode))
118 #define MODE_N1(mode) (PWATM_MODE_N1_NOCW == (mode)|| PWATM_MODE_N1_CW == (mode))
119 #define MODE_11_OR_AAL5_PDU(mode) (MODE_11(mode) || PWATM_MODE_AAL5_PDU == (mode))
121 #define VALUE_SELECTOR_VPC_VCC_PDU(mode,val_vpc,val_vcc,val_pdu)\
122 ((PWATM_MODE_11_VPC == (mode)) \
124 : ((PWATM_MODE_11_VCC == (mode)) \
126 : ((PWATM_MODE_AAL5_PDU == (mode)) \
133 #define UPDATE_CUMULATIVE_VALUE(cumulative_val,new_val)\
136 if (-2 >= (cumulative_val))\
139 else if (-1 == (cumulative_val))\
141 (cumulative_val) = (new_val);\
143 else if ((new_val) != (cumulative_val))\
145 (cumulative_val) = -2;\
150 #define SIZEOF_ATM_CELL_PAYLOAD 48
151 #define SIZEOF_N1_PW_CELL_HEADER 4
152 #define SIZEOF_11_VCC_PW_CELL_HEADER 1
153 #define SIZEOF_11_VPC_PW_CELL_HEADER 3
154 #define SIZEOF_N1_PW_CELL (SIZEOF_ATM_CELL_PAYLOAD+SIZEOF_N1_PW_CELL_HEADER)
155 #define SIZEOF_11_VCC_PW_CELL (SIZEOF_ATM_CELL_PAYLOAD+SIZEOF_11_VCC_PW_CELL_HEADER)
156 #define SIZEOF_11_VPC_PW_CELL (SIZEOF_ATM_CELL_PAYLOAD+SIZEOF_11_VPC_PW_CELL_HEADER)
158 const char pwc_longname_pw_atm_n1_cw[] = "MPLS PW ATM N-to-One encapsulation, with CW";
159 const char pwc_longname_pw_atm_n1_nocw[] = "MPLS PW ATM N-to-One encapsulation, no CW";
160 const char pwc_longname_pw_atm_11_or_aal5_pdu[] = "MPLS PW ATM One-to-One or AAL5 PDU encapsulation";
161 const char pwc_longname_pw_atm_aal5_sdu[] = "MPLS PW ATM AAL5 CPCS-SDU mode encapsulation";
163 static const char longname_pw_atm_11_vcc[] = "MPLS PW ATM One-to-One VCC Cell Transport";
164 static const char longname_pw_atm_11_vpc[] = "MPLS PW ATM One-to-One VPC Cell Transport";
165 static const char longname_pw_atm_aal5_pdu[] = "MPLS PW ATM AAL5 PDU encapsulation";
167 static const char shortname_n1_cw[] = "MPLS PW ATM N:1 CW";
168 static const char shortname_n1_nocw[] = "MPLS PW ATM N:1 no CW";
169 static const char shortname_11_or_aal5_pdu[] = "MPLS PW ATM 1:1 / AAL5 PDU";
170 static const char shortname_11_vpc[] = "MPLS PW ATM 1:1 VPC";
171 static const char shortname_11_vcc[] = "MPLS PW ATM 1:1 VCC";
172 static const char shortname_aal5_sdu[] = "MPLS PW ATM AAL5 SDU";
173 static const char shortname_aal5_pdu[] = "MPLS PW ATM AAL5 PDU";
176 * These options are needed to support Nokia AXE and stuff alike.
177 * Note that these options will affect PW type auto-guessing, if such heuristic
178 * implemented in the future.
180 static gboolean pref_n1_cw_allow_cw_length_nonzero = FALSE;
181 static gboolean pref_n1_cw_extend_cw_length_with_rsvd = FALSE;
182 static gboolean pref_aal5_sdu_allow_cw_length_nonzero = FALSE;
183 static gboolean pref_aal5_sdu_extend_cw_length_with_rsvd= FALSE;
187 int pw_cell_size(const pwatm_mode_t mode, const pwatm_submode_t submode)
191 case PWATM_MODE_N1_NOCW:
192 case PWATM_MODE_N1_CW:
193 return SIZEOF_N1_PW_CELL;
194 case PWATM_MODE_11_VCC:
195 return SIZEOF_11_VCC_PW_CELL;
196 case PWATM_MODE_11_VPC:
197 return SIZEOF_11_VPC_PW_CELL;
198 case PWATM_MODE_AAL5_PDU:
199 /* AAL5 PDU size is n*48 bytes */
200 return SIZEOF_ATM_CELL_PAYLOAD;
201 case PWATM_MODE_AAL5_SDU:
202 if (PWATM_SUBMODE_ADMIN_CELL == submode)
204 return SIZEOF_N1_PW_CELL; /*n:1 encapsulation is used for admin cells*/
208 DISSECTOR_ASSERT_NOT_REACHED();
212 DISSECTOR_ASSERT_NOT_REACHED();
218 int pw_cell_header_size(const pwatm_mode_t mode, const pwatm_submode_t submode)
222 case PWATM_MODE_N1_NOCW:
223 case PWATM_MODE_N1_CW:
224 return SIZEOF_N1_PW_CELL_HEADER;
225 case PWATM_MODE_11_VCC:
226 return SIZEOF_11_VCC_PW_CELL_HEADER;
227 case PWATM_MODE_11_VPC:
228 return SIZEOF_11_VPC_PW_CELL_HEADER;
229 case PWATM_MODE_AAL5_SDU:
230 if (PWATM_SUBMODE_ADMIN_CELL == submode)
232 return SIZEOF_N1_PW_CELL_HEADER; /*n:1 encapsulation is used for admin cells*/
236 DISSECTOR_ASSERT_NOT_REACHED();
239 case PWATM_MODE_AAL5_PDU: /*not applicable*/
241 DISSECTOR_ASSERT_NOT_REACHED();
247 int number_of_cells(const pwatm_mode_t mode
248 ,const pwatm_submode_t submode
249 ,const gint payload_size
250 ,gint* const remainder_size)
254 DISSECTOR_ASSERT(payload_size >= 0);
258 case PWATM_MODE_N1_NOCW:
259 case PWATM_MODE_N1_CW:
260 case PWATM_MODE_11_VCC:
261 case PWATM_MODE_11_VPC:
262 case PWATM_MODE_AAL5_PDU:
263 cells = payload_size / pw_cell_size(mode,submode);
264 *remainder_size = payload_size - (cells * pw_cell_size(mode,submode));
266 case PWATM_MODE_AAL5_SDU:
267 if (PWATM_SUBMODE_ADMIN_CELL == submode)
269 cells = payload_size / pw_cell_size(mode,submode);
270 if (cells > 1) cells = 1; /*max. 1 admin cell may be present in aal5 sdu mode */
271 *remainder_size = payload_size - (cells * pw_cell_size(mode,submode));
280 DISSECTOR_ASSERT_NOT_REACHED();
281 *remainder_size = payload_size;
289 void col_append_pw_info(packet_info * pinfo
290 ,const int payload_size
292 ,const int padding_size)
294 pwatm_private_data_t* pd;
295 DISSECTOR_ASSERT(pinfo != NULL);
297 pd = pinfo->private_data;
298 DISSECTOR_ASSERT(pd != NULL);
300 if (pd->props & PWC_ANYOF_CW_BAD)
302 col_append_str(pinfo->cinfo, COL_INFO, "CW:Bad");
305 if (pd->props & PWC_PAY_SIZE_BAD)
307 if (pd->props & PWC_ANYOF_CW_BAD)
309 col_append_str(pinfo->cinfo, COL_INFO, ", ");
311 col_append_str(pinfo->cinfo, COL_INFO, "Payload size:Bad, ");
312 col_append_fstr(pinfo->cinfo, COL_INFO, "%d byte%s"
314 ,plurality(payload_size,"","s"));
317 if (pd->props == 0) /*omit "atm cells" etc if something is wrong*/
319 /* number of cells may be not known */
321 col_append_fstr(pinfo->cinfo, COL_INFO, "%d ATM cell%s"
323 ,plurality(cells,"","s"));
325 * Display ATM-specific attributes which are the same
326 * across all the cells in the pw packet.
327 * Meanings of values:
328 * (-1) unknown - not displayed,
329 * (-2) "not the same in all cells" - not displayed
330 * positive values - ok, displayed
332 if (pd->cumulative.vpi >= 0)
333 col_append_fstr(pinfo->cinfo, COL_INFO, ", VPI:%.4d", pd->cumulative.vpi);
334 if (pd->cumulative.vci >= 0)
335 col_append_fstr(pinfo->cinfo, COL_INFO, ", VCI:%.5d", pd->cumulative.vci);
336 if (pd->cumulative.pti >= 0)
337 col_append_fstr(pinfo->cinfo, COL_INFO, ", PTI:%.1d", pd->cumulative.pti);
338 if (pd->cumulative.clp >= 0)
339 col_append_fstr(pinfo->cinfo, COL_INFO, ", CLP:%.1d", pd->cumulative.clp);
342 if (padding_size != 0)
344 col_append_fstr(pinfo->cinfo, COL_INFO, ", %d padding"
351 void prepare_pseudo_header_atm(
352 union wtap_pseudo_header * const ph,
353 const pwatm_private_data_t * const pdata,
356 DISSECTOR_ASSERT(NULL != pdata);
357 DISSECTOR_ASSERT(NULL != ph);
359 memset(ph,0,sizeof(*ph)); /* it is OK to clear unknown values */
360 ph->atm.flags = 0; /* status flags */
362 ph->atm.type = TRAF_UNKNOWN;
363 ph->atm.subtype = TRAF_ST_UNKNOWN;
364 ph->atm.vpi = (pdata->vpi >= 0) ? pdata->vpi : 0 /*unknown*/;
365 ph->atm.vci = (pdata->vci >= 0) ? pdata->vci : 0 /*unknown*/;
366 ph->atm.aal2_cid = 0; /*not applicable*//* channel id */
367 ph->atm.channel = 0; /*unknown*//* link: 0 for DTE->DCE, 1 for DCE->DTE */
368 ph->atm.cells = 0; /*zero indicates that we do not have trailer info*/
369 /*user-to-user indicator & CPI*/
370 ph->atm.aal5t_u2u = 0; /* all bits unknown except lsb of UU */
371 if (pdata->aal5_sdu_frame_relay_cr_bit)
372 { /* Let's give Frame Relay C/R bit to ATM dissector.*/
373 ph->atm.aal5t_u2u |= (1<<8); /*UU octet is at << 8 in aal5t_u2u*/
375 ph->atm.aal5t_len = 0; /*unknown*//* length of the packet from trailer*/
376 ph->atm.aal5t_chksum = 0; /*unknown*//* checksum for AAL5 packet from trailer */
382 void dissect_payload_and_padding(
386 ,const gint payload_size
387 ,const gint padding_size)
391 pwatm_private_data_t* pd;
393 DISSECTOR_ASSERT(NULL != pinfo);
394 pd = pinfo->private_data;
395 DISSECTOR_ASSERT(NULL != pd);
397 for(dissected = 0, pd->pw_cell_number = 0;
398 payload_size > dissected;
399 ++(pd->pw_cell_number))
401 tvb_2 = tvb_new_subset_remaining(tvb,dissected);
402 dissected += call_dissector(dh_cell_header, tvb_2, pinfo, tree);
404 tvb_2 = tvb_new_subset_remaining(tvb,dissected);
406 /*dissect as oam for specific vci/pti, just like atm dissector does*/
407 if (pd->vci >= 0 && pd->pti >=0)
409 if (atm_is_oam_cell(pd->vci,pd->pti))
411 pd->cell_mode_oam = TRUE;
415 if (pd->cell_mode_oam)
417 union wtap_pseudo_header* pseudo_header_save;
418 union wtap_pseudo_header ph;
420 int bytes_to_dissect;
421 /* prepare buffer for old-style dissector */
422 /* oam cell is always 48 bytes, but payload_size maybe too small */
423 if ((payload_size - dissected) >= SIZEOF_ATM_CELL_PAYLOAD)
424 bytes_to_dissect = SIZEOF_ATM_CELL_PAYLOAD;
426 bytes_to_dissect = (payload_size - dissected);
427 tvb_3 = tvb_new_subset(tvb_2,0,bytes_to_dissect,-1);
428 /*aal5_sdu: disable filling columns after 1st (valid) oam cell*/
429 if (pd->mode == PWATM_MODE_AAL5_SDU && pd->pw_cell_number > 0)
431 pd->enable_fill_columns_by_atm_dissector = FALSE;
433 /* save & prepare new pseudo header for atm aal5 decoding */
434 pseudo_header_save = pinfo->pseudo_header;
435 pinfo->pseudo_header = &ph;
436 prepare_pseudo_header_atm(&ph,pd,AAL_OAMCELL);
438 call_dissector(dh_atm_oam_cell, tvb_3, pinfo, tree);
439 dissected += bytes_to_dissect;
440 /* restore pseudo header */
441 pinfo->pseudo_header = pseudo_header_save;
445 dissected += call_dissector(dh_cell, tvb_2, pinfo, tree);
449 if (padding_size != 0)
452 tvb_2 = tvb_new_subset(tvb
453 ,(tvb_reported_length_remaining(tvb, 0) - padding_size)
456 call_dissector(dh_padding, tvb_2, pinfo, tree);
463 gboolean too_small_packet_or_notpw(tvbuff_t * tvb
466 ,const int proto_handler
467 ,const char * const proto_name_column)
470 packet_size = tvb_reported_length_remaining(tvb, 0);
473 * "4" below should be replaced by something like "min_packet_size_this_dissector"
474 * Also call to dissect_try_cw_first_nibble() should be moved before this block
476 if (packet_size < 4) /* 4 is smallest size which may be sensible (for PWACH dissector) */
481 item = proto_tree_add_item(tree, proto_handler, tvb, 0, -1, FALSE);
482 expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR,
483 "PW packet size (%d) is too small to carry sensible information"
486 /* represent problems in the Packet List pane */
487 if (check_col(pinfo->cinfo, COL_PROTOCOL))
489 col_set_str(pinfo->cinfo, COL_PROTOCOL, proto_name_column);
491 col_set_str(pinfo->cinfo, COL_INFO, "Malformed: PW packet is too small");
494 if (dissect_try_cw_first_nibble(tvb, pinfo, tree))
503 * NOTE. RFC describes ATM-specific byte in a cumbersome way.
504 * It is a part of CW, but at the same time, it must be repeated
505 * with each cell, _except_ first.
507 * Alternatively, ATM-specific byte may be considered as part of
508 * PW payload (i.e., as part of pw atm cell header), so we can say that
509 * it is being repeated with each cell.
511 * This dissector is written according to the latter consideration.
514 void dissect_11_or_aal5_pdu(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
516 const char *proto_name_column;
517 const char *proto_name_tree = NULL;
520 pwatm_private_data_t pd = PWATM_PRIVATE_DATA_T_INITIALIZER;
521 void * pd_save = pinfo->private_data;
522 pinfo->private_data = &pd;
524 proto_name_column = &shortname_11_or_aal5_pdu[0];
525 if (too_small_packet_or_notpw(tvb,pinfo,tree,proto_11_or_aal5_pdu,proto_name_column))
529 pd.packet_size = tvb_reported_length_remaining(tvb, 0);
532 * Guess encapsulation mode according to M & V bits from the 3rd byte of CW.
533 * Also adjust protocol name strings.
537 third_byte = tvb_get_guint8(tvb, 3);
538 if (0 == (third_byte & 0x80 /*generic_cw.m*/))
540 if (0 != (third_byte & 0x40 /*generic_cw.v*/))
542 pd.mode = PWATM_MODE_11_VPC;
543 proto_name_column = &shortname_11_vpc[0];
544 proto_name_tree = &longname_pw_atm_11_vpc[0];
548 pd.mode = PWATM_MODE_11_VCC;
549 proto_name_column = &shortname_11_vcc[0];
550 proto_name_tree = &longname_pw_atm_11_vcc[0];
555 pd.mode = PWATM_MODE_AAL5_PDU;
556 proto_name_column = &shortname_aal5_pdu[0];
557 proto_name_tree = &longname_pw_atm_aal5_pdu[0];
562 /* check how "good" is this packet */
563 pd.props = PWC_PACKET_PROPERTIES_T_INITIALIZER;
564 if (0 != (tvb_get_guint8(tvb, 0) & 0xf0 /*bits03*/))
566 pd.props |= PWC_CW_BAD_BITS03;
568 if (0 != (tvb_get_guint8(tvb, 0) & 0x0f /*generic_cw.rsvd*/))
570 pd.props |= PWC_CW_BAD_RSV;
574 * Do not dissect and validate atm-specific byte (3rd byte of CW).
575 * It will be dissected/validated as pw cell header.
579 * Decide about payload length and padding.
581 * Is padding allowed?
582 * eth header length == 14
583 * mpls label length == 4
585 * min payload length == 48
586 * => 14 + 4 + 4 + 48 == 70
588 * => no padding allowed
590 if (MODE_11(pd.mode))
592 gint bad_padding_size;
593 payload_size = pd.packet_size - (PWC_SIZEOF_CW-1);
594 cells = number_of_cells(pd.mode,pd.submode,payload_size,&bad_padding_size);
595 if (0 == cells || 0 != bad_padding_size)
597 pd.props |= PWC_PAY_SIZE_BAD;
602 gint bad_padding_size;
603 payload_size = pd.packet_size - PWC_SIZEOF_CW;
604 cells = number_of_cells(pd.mode,pd.submode,payload_size,&bad_padding_size);
605 /* at least 1 cell must be present in the packet in this mode*/
606 if (1 > cells || 0 != bad_padding_size)
608 pd.props |= PWC_PAY_SIZE_BAD;
610 cells = -1; /*this value not needed anymore, suppress pinting of it*/
613 if (PWATM_MODE_AAL5_PDU == pd.mode)
615 /* sub-dissectors _may_ overwrite columns in aal5_pdu mode */
616 if (check_col(pinfo->cinfo, COL_PROTOCOL))
618 col_set_str(pinfo->cinfo, COL_PROTOCOL, proto_name_column);
620 if (check_col(pinfo->cinfo, COL_INFO))
622 col_clear(pinfo->cinfo, COL_INFO);
623 col_append_pw_info(pinfo, payload_size, cells, 0);
630 item = proto_tree_add_item(tree, proto_11_or_aal5_pdu, tvb, 0, -1, FALSE);
631 /*overwrite heading line*/
632 proto_item_set_text(item, proto_name_tree, 0/*-warn gcc 3.4.4*/);
633 pwc_item_append_text_n_items(item,cells,"good ATM cell");
636 tree = proto_item_add_subtree(item, ett_encaps);
639 item = proto_tree_add_boolean(tree
640 ,VALUE_SELECTOR_VPC_VCC_PDU(pd.mode
643 ,hf_pw_type_aal5_pdu)
645 PROTO_ITEM_SET_GENERATED(item);
646 if (MODE_11(pd.mode))
648 item = proto_tree_add_int(tree, hf_11_ncells, tvb, 0, 0, cells);
649 PROTO_ITEM_SET_GENERATED(item);
653 if (pd.props & PWC_PAY_SIZE_BAD)
655 expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR
656 ,"PW payload size (%d) must be <> 0 and multiple of %d"
657 ,(int)payload_size,pw_cell_size(pd.mode,pd.submode));
658 if (payload_size != 0 && MODE_11(pd.mode))
660 expert_add_info_format(pinfo, item, PI_MALFORMED, PI_NOTE,
661 "PW ATM cell [%.3d] is broken",(int)cells);
668 tvb_2 = tvb_new_subset(tvb, 0, PWC_SIZEOF_CW, PWC_SIZEOF_CW);
669 call_dissector(dh_control_word, tvb_2, pinfo, tree);
671 tvb_2 = tvb_new_subset(tvb, (PWC_SIZEOF_CW-1), -1, -1);
672 if (MODE_11(pd.mode))
674 dissect_payload_and_padding(tvb_2,pinfo,tree,payload_size,0);
678 if (payload_size != 0)
681 union wtap_pseudo_header* pseudo_header_save;
682 union wtap_pseudo_header ph;
684 tvb_3 = tvb_new_subset_remaining(tvb_2, 1);
685 /* prepare pseudo header for atm aal5 decoding */
686 pseudo_header_save = pinfo->pseudo_header;
687 pinfo->pseudo_header = &ph;
688 prepare_pseudo_header_atm(&ph,&pd,AAL_5);
689 call_dissector(dh_atm_untruncated, tvb_3, pinfo, tree);
690 /* restore pseudo header */
691 pinfo->pseudo_header = pseudo_header_save;
696 if (MODE_11(pd.mode))
698 /* overwrite everything written by sub-dissectors in 1:1 modes*/
699 if (check_col(pinfo->cinfo, COL_PROTOCOL))
701 col_set_str(pinfo->cinfo, COL_PROTOCOL, proto_name_column);
703 if (check_col(pinfo->cinfo, COL_INFO))
705 col_clear(pinfo->cinfo, COL_INFO);
706 col_append_pw_info(pinfo, payload_size, cells, 0);
710 pinfo->private_data = pd_save;
716 void dissect_aal5_sdu(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
718 const char *proto_name_column;
722 pwatm_private_data_t pd = PWATM_PRIVATE_DATA_T_INITIALIZER;
723 void * pd_save = pinfo->private_data;
725 pinfo->private_data = &pd;
726 pd.mode = PWATM_MODE_AAL5_SDU;
728 proto_name_column = &shortname_aal5_sdu[0];
729 if (too_small_packet_or_notpw(tvb,pinfo,tree,proto_aal5_sdu,proto_name_column))
733 pd.packet_size = tvb_reported_length_remaining(tvb, 0);
735 /* check how "good" is this packet */
736 /* also decide payload length from packet size and CW */
737 if (0 != (tvb_get_guint8(tvb, 0) & 0xf0 /*bits03*/))
739 pd.props |= PWC_CW_BAD_BITS03;
742 pd.submode = PWATM_SUBMODE_DEFAULT;
743 if (0 != (tvb_get_guint8(tvb, 0) & 0x08 /*preferred_cw.T*/))
745 pd.submode = PWATM_SUBMODE_ADMIN_CELL;
748 if (! pref_aal5_sdu_extend_cw_length_with_rsvd)
750 if (0 != (tvb_get_guint8(tvb, 1) & 0xc0 /*preferred_cw.rsvd*/))
752 pd.props |= PWC_CW_BAD_RSV;
757 * [ If the packet's length (defined as the length of the layer 2 payload
758 * plus the length of the control word) is less than 64 bytes, the
759 * length field MUST be set to the packet's length. Otherwise, the
760 * length field MUST be set to zero... Note that the length field
761 * is not used in the N-to-one mode and MUST be set to 0. ]
763 * Also we allow some "extensions"conducted by pref_xxx.
765 gint payload_size_from_packet;
766 int cw_len; /*length field from cw*/
768 payload_size_from_packet = pd.packet_size - PWC_SIZEOF_CW;
769 if (pref_aal5_sdu_extend_cw_length_with_rsvd)
771 cw_len = tvb_get_guint8(tvb, 1) & 0xff;
775 cw_len = tvb_get_guint8(tvb, 1) & 0x3f;
779 * Initial assumptions: no padding,
780 * payload size derived from psn packet size.
782 payload_size = payload_size_from_packet;
787 /*keep initial assumptions*/
789 else if (!pref_aal5_sdu_allow_cw_length_nonzero
790 && PWATM_SUBMODE_ADMIN_CELL == pd.submode)
793 * The "allow CW.Length != 0" option affects
794 * ATM admin cell submode only, because this submode
795 * is equal to N:1 encapsulation.
796 * CW.Length !=0 is always OK for normal (AAL5 payload) submode.
798 pd.props |= PWC_CW_BAD_LEN_MUST_BE_0;
802 gint payload_size_from_cw;
803 payload_size_from_cw = cw_len - PWC_SIZEOF_CW;
804 if (payload_size_from_cw <= 0)
806 pd.props |= PWC_CW_BAD_PAYLEN_LE_0;
808 else if (payload_size_from_cw > payload_size_from_packet)
810 pd.props |= PWC_CW_BAD_PAYLEN_GT_PACKET;
815 payload_size = payload_size_from_cw;
816 padding_size = payload_size_from_packet - payload_size_from_cw; /* >=0 */
817 if (padding_size != 0)
820 * Padding is not allowed in ATM admin cell submode only,
821 * because this submode is equal to N:1 encapsulation.
822 * Padding is OK for normal (AAL5 payload) submode.
824 if (PWATM_SUBMODE_ADMIN_CELL == pd.submode)
826 pd.props |= PWC_CW_BAD_PADDING_NE_0;
828 payload_size = payload_size_from_packet;
835 if (PWATM_SUBMODE_ADMIN_CELL == pd.submode)
837 gint bad_padding_size;
838 cells = number_of_cells(pd.mode,pd.submode,payload_size,&bad_padding_size);
839 /* only one atm admin cell is allowed in the packet in this mode*/
840 if (1 != cells || 0 != bad_padding_size)
842 pd.props |= PWC_PAY_SIZE_BAD;
847 cells = -1; /*unknown*/
848 /* Any size is allowed for AAL5 SDU payload */
852 /* fill columns in Packet List */
853 if (check_col(pinfo->cinfo, COL_PROTOCOL))
855 col_set_str(pinfo->cinfo, COL_PROTOCOL, proto_name_column);
856 if (PWATM_SUBMODE_ADMIN_CELL == pd.submode)
858 col_append_str(pinfo->cinfo, COL_PROTOCOL, ", OAM cell");
862 if (check_col(pinfo->cinfo, COL_INFO))
864 col_clear(pinfo->cinfo, COL_INFO);
865 col_append_pw_info(pinfo, payload_size, cells, padding_size);
871 item = proto_tree_add_item(tree, proto_aal5_sdu, tvb, 0, -1, FALSE);
874 tree = proto_item_add_subtree(item, ett_encaps);
876 item = proto_tree_add_boolean(tree, hf_pw_type_aal5_sdu, tvb, 0, 0, TRUE);
877 PROTO_ITEM_SET_GENERATED(item);
880 if (pd.props & PWC_PAY_SIZE_BAD)
882 DISSECTOR_ASSERT(PWATM_SUBMODE_ADMIN_CELL == pd.submode);
883 expert_add_info_format(pinfo, item, PI_MALFORMED ,PI_ERROR
884 ,"In ATM admin cell mode,"
885 " PW payload size (%d) must be == %d (exactly 1 admin cell)"
886 ,(int)payload_size,(int)SIZEOF_N1_PW_CELL);
892 tvb_2 = tvb_new_subset(tvb, 0, PWC_SIZEOF_CW, PWC_SIZEOF_CW);
893 call_dissector(dh_control_word, tvb_2, pinfo, tree);
895 tvb_2 = tvb_new_subset_remaining(tvb, PWC_SIZEOF_CW);
896 if (PWATM_SUBMODE_ADMIN_CELL == pd.submode)
898 dissect_payload_and_padding(tvb_2,pinfo,tree,payload_size,padding_size);
900 else /*AAL5 payload*/
902 if (payload_size != 0)
905 union wtap_pseudo_header* pseudo_header_save;
906 union wtap_pseudo_header ph;
908 tvb_3 = tvb_new_subset(tvb_2, 0, payload_size, payload_size);
909 /* prepare pseudo header for atm aal5 decoding */
910 pseudo_header_save = pinfo->pseudo_header;
911 pinfo->pseudo_header = &ph;
912 prepare_pseudo_header_atm(&ph,&pd,AAL_5);
913 call_dissector(dh_atm_truncated, tvb_3, pinfo, tree); /* no PAD and trailer */
914 /* restore pseudo header */
915 pinfo->pseudo_header = pseudo_header_save;
917 if (padding_size != 0)
920 tvb_3 = tvb_new_subset(tvb_2, payload_size, padding_size, -1);
921 call_dissector(dh_padding, tvb_3, pinfo, tree);
926 pinfo->private_data = pd_save;
932 void dissect_n1_cw(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
934 const char *proto_name_column;
938 pwatm_private_data_t pd = PWATM_PRIVATE_DATA_T_INITIALIZER;
939 void * pd_save = pinfo->private_data;
941 pinfo->private_data = &pd;
942 pd.mode = PWATM_MODE_N1_CW;
944 proto_name_column = &shortname_n1_cw[0];
945 if (too_small_packet_or_notpw(tvb,pinfo,tree,proto_n1_cw,proto_name_column))
949 pd.packet_size = tvb_reported_length_remaining(tvb, 0);
951 /* check how "good" is this packet */
952 /* also decide payload length from packet size and CW */
953 pd.props = PWC_PACKET_PROPERTIES_T_INITIALIZER;
954 if (0 != (tvb_get_guint8(tvb, 0) & 0xf0 /*bits03*/))
956 pd.props |= PWC_CW_BAD_BITS03;
958 if (0 != (tvb_get_guint8(tvb, 0) & 0x0f /*preferred_cw.flags*/))
960 pd.props |= PWC_CW_BAD_FLAGS;
962 if (! pref_n1_cw_extend_cw_length_with_rsvd)
964 if (0 != (tvb_get_guint8(tvb, 1) & 0xc0 /*preferred_cw.rsvd*/))
966 pd.props |= PWC_CW_BAD_RSV;
971 * [ If the packet's length (defined as the length of the layer 2 payload
972 * plus the length of the control word) is less than 64 bytes, the
973 * length field MUST be set to the packet's length. Otherwise, the
974 * length field MUST be set to zero... Note that the length field
975 * is not used in the N-to-one mode and MUST be set to 0. ]
977 * Also we allow some "extensions"conducted by pref_xxx.
979 gint payload_size_from_packet;
980 int cw_len; /*length field from cw*/
982 payload_size_from_packet = pd.packet_size - PWC_SIZEOF_CW;
983 if (pref_n1_cw_extend_cw_length_with_rsvd)
985 cw_len = tvb_get_guint8(tvb, 1) & 0xff;
989 cw_len = tvb_get_guint8(tvb, 1) & 0x3f;
993 * Initial assumptions: no padding,
994 * payload size derived from psn packet size.
996 payload_size = payload_size_from_packet;
1001 /*keep initial assumptions*/
1003 else if (!pref_n1_cw_allow_cw_length_nonzero)
1005 pd.props |= PWC_CW_BAD_LEN_MUST_BE_0;
1009 gint payload_size_from_cw;
1010 payload_size_from_cw = cw_len - PWC_SIZEOF_CW;
1011 if (payload_size_from_cw <= 0)
1013 pd.props |= PWC_CW_BAD_PAYLEN_LE_0;
1015 else if (payload_size_from_cw > payload_size_from_packet)
1017 pd.props |= PWC_CW_BAD_PAYLEN_GT_PACKET;
1022 payload_size = payload_size_from_cw;
1023 padding_size = payload_size_from_packet - payload_size_from_cw; /* >=0 */
1024 if (padding_size != 0)
1026 pd.props |= PWC_CW_BAD_PADDING_NE_0;
1028 payload_size = payload_size_from_packet;
1034 gint bad_padding_size;
1035 cells = number_of_cells(pd.mode,pd.submode,payload_size,&bad_padding_size);
1036 if (0 == cells || 0 != bad_padding_size)
1038 pd.props |= PWC_PAY_SIZE_BAD;
1046 item = proto_tree_add_item(tree, proto_n1_cw, tvb, 0, -1, FALSE);
1047 pwc_item_append_text_n_items(item,cells,"good ATM cell");
1050 tree = proto_item_add_subtree(item, ett_encaps);
1053 item = proto_tree_add_boolean(tree, hf_pw_type_n1_cw, tvb, 0, 0, TRUE);
1054 PROTO_ITEM_SET_GENERATED(item);
1055 item = proto_tree_add_int(tree, hf_n1_cw_ncells, tvb, 0, 0, cells);
1056 PROTO_ITEM_SET_GENERATED(item);
1059 if (pd.props & PWC_PAY_SIZE_BAD)
1061 if (payload_size != 0)
1063 expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR,
1064 "PW ATM cell [%.3d] is broken",(int)cells);
1066 expert_add_info_format(pinfo, item, PI_MALFORMED
1067 , (payload_size == 0) ? PI_ERROR : PI_NOTE
1068 ,"PW payload size (%d) must be <>0 and multiple of %d"
1069 ,(int)payload_size,(int)SIZEOF_N1_PW_CELL);
1075 tvb_2 = tvb_new_subset(tvb, 0, PWC_SIZEOF_CW, PWC_SIZEOF_CW);
1076 call_dissector(dh_control_word, tvb_2, pinfo, tree);
1078 tvb_2 = tvb_new_subset_remaining(tvb, PWC_SIZEOF_CW);
1079 dissect_payload_and_padding(tvb_2,pinfo,tree,payload_size,padding_size);
1082 /* fill columns in Packet List */
1083 /* overwrite everything written by sub-dissectors */
1084 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1086 col_set_str(pinfo->cinfo, COL_PROTOCOL, proto_name_column);
1089 if (check_col(pinfo->cinfo, COL_INFO))
1091 col_clear(pinfo->cinfo, COL_INFO);
1092 col_append_pw_info(pinfo, payload_size, cells, padding_size);
1095 pinfo->private_data = pd_save;
1101 void dissect_n1_nocw(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
1103 const char *proto_name_column = &shortname_n1_nocw[0];
1106 pwatm_private_data_t pd = PWATM_PRIVATE_DATA_T_INITIALIZER;
1107 void * pd_save = pinfo->private_data;
1109 pinfo->private_data = &pd;
1110 pd.mode = PWATM_MODE_N1_NOCW;
1111 pd.packet_size = tvb_reported_length_remaining(tvb, 0);
1113 /* check how "good" is this packet */
1114 /* also decide payload length from packet size */
1115 pd.props = PWC_PACKET_PROPERTIES_T_INITIALIZER;
1116 payload_size = pd.packet_size;
1118 gint bad_padding_size;
1119 cells = number_of_cells(pd.mode,pd.submode,pd.packet_size,&bad_padding_size);
1120 if (cells == 0 || bad_padding_size != 0)
1122 pd.props |= PWC_PAY_SIZE_BAD;
1129 item = proto_tree_add_item(tree, proto_n1_nocw, tvb, 0, -1, FALSE);
1130 pwc_item_append_text_n_items(item,cells,"ATM cell");
1133 tree = proto_item_add_subtree(item, ett_encaps);
1136 item = proto_tree_add_boolean(tree, hf_pw_type_n1_nocw, tvb, 0, 0, TRUE);
1137 PROTO_ITEM_SET_GENERATED(item);
1138 item = proto_tree_add_int(tree, hf_n1_nocw_ncells, tvb, 0, 0, cells);
1139 PROTO_ITEM_SET_GENERATED(item);
1142 if (pd.props & PWC_PAY_SIZE_BAD)
1144 if (payload_size != 0)
1146 expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR,
1147 "Last PW ATM cell [%.3d] is broken",(int)cells);
1149 expert_add_info_format(pinfo, item, PI_MALFORMED
1150 , (payload_size == 0) ? PI_ERROR : PI_NOTE
1151 ,"PW payload size (%d) must be <>0 and multiple of %d"
1152 ,(int)payload_size,(int)SIZEOF_N1_PW_CELL);
1156 dissect_payload_and_padding(tvb,pinfo,tree,payload_size,0);
1158 /* fill columns in Packet List */
1159 /* overwrite everything written by sub-dissectors */
1160 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1162 col_set_str(pinfo->cinfo, COL_PROTOCOL, proto_name_column);
1165 if (check_col(pinfo->cinfo, COL_INFO))
1167 col_clear(pinfo->cinfo, COL_INFO);
1168 col_append_pw_info(pinfo, payload_size, cells, 0);
1171 pinfo->private_data = pd_save;
1177 void proto_item_append_text_cwb3_fields(proto_item * item, const pwatm_private_data_t * const pd)
1179 if (NULL == item) return;
1180 DISSECTOR_ASSERT(NULL != pd);
1181 if (pd->cwb3.m >= 0)
1182 proto_item_append_text(item, "M:%.1u " , (unsigned)(pd->cwb3.m));
1183 if (pd->cwb3.v >= 0)
1184 proto_item_append_text(item, "V:%.1u " , (unsigned)(pd->cwb3.v));
1185 if (pd->cwb3.rsv >= 0)
1186 proto_item_append_text(item, "RSV:%.1u ", (unsigned)(pd->cwb3.rsv));
1187 if (pd->cwb3.u >= 0)
1188 proto_item_append_text(item, "U:%.1u " , (unsigned)(pd->cwb3.u));
1189 if (pd->cwb3.e >= 0)
1190 proto_item_append_text(item, "EFCI:%.1u ",(unsigned)(pd->cwb3.e));
1191 if (pd->cwb3.clp >= 0)
1192 proto_item_append_text(item, "CLP:%.1u ", (unsigned)(pd->cwb3.clp));
1198 void dissect_control_word(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
1200 pwatm_private_data_t* pd;
1201 pd = pinfo->private_data;
1202 DISSECTOR_ASSERT(pd != NULL);
1205 * NB: do not touch columns -- keep info from previous dissector
1210 size = tvb_reported_length_remaining(tvb, 0);
1211 if (size < PWC_SIZEOF_CW)
1216 item = proto_tree_add_item(tree, proto_control_word, tvb, 0, -1, FALSE);
1217 expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR,
1218 "Packet (size: %d) is too small to carry MPLS PW Control Word"
1227 proto_item* item_top;
1228 item_top = proto_tree_add_item(tree, proto_control_word, tvb, 0, -1, FALSE);
1229 pwc_item_append_cw(item_top,tvb_get_ntohl(tvb, 0),FALSE);
1233 tree = proto_item_add_subtree(item_top, ett_cw);
1237 item = proto_tree_add_item(tree, hf_cw_bits03, tvb, 0, 1, FALSE);
1238 if (pd->props & PWC_CW_BAD_BITS03)
1240 /* add item to tree (and show it) only if its value is wrong*/
1241 expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR
1242 ,"Bits 0..3 of Control Word must be 0");
1246 PROTO_ITEM_SET_HIDDEN(item); /* show only in error cases */
1250 if (MODE_N1(pd->mode))
1252 item = proto_tree_add_item(tree, hf_pref_cw_flags, tvb, 0, 1, FALSE);
1253 if (pd->props & PWC_CW_BAD_FLAGS)
1255 expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR
1256 ,"Flags must be 0 for PW ATM N:1 encapsulation");
1259 if (pd->mode == PWATM_MODE_AAL5_SDU)
1261 item = proto_tree_add_item(tree, hf_pref_cw_a5s_t, tvb, 0, 1, FALSE);
1262 item = proto_tree_add_item(tree, hf_pref_cw_a5s_e, tvb, 0, 1, FALSE);
1263 item = proto_tree_add_item(tree, hf_pref_cw_a5s_c, tvb, 0, 1, FALSE);
1264 item = proto_tree_add_item(tree, hf_pref_cw_a5s_u, tvb, 0, 1, FALSE);
1266 * rfc4717: [When FRF.8.1 Frame Relay/ATM PVC Service Interworking [RFC3916]
1267 * traffic is being transported, the CPCS-UU Least Significant Bit
1268 * (LSB) of the AAL5 CPCS-PDU may contain the Frame Relay C/R bit.
1269 * The ingress router, PE1, SHOULD copy this bit to the U bit of the
1270 * control word. The egress router, PE2, SHOULD copy the U bit to
1271 * the CPCS-UU Least Significant Bit (LSB) of the AAL5 CPCS PDU.]
1273 * Let's remember this bit (and then transfer it to ATM dissector).
1275 pd->aal5_sdu_frame_relay_cr_bit =
1276 (0 == (tvb_get_guint8(tvb, 0) & 0x01 /*preferred_cw.U*/))
1281 if (MODE_11_OR_AAL5_PDU(pd->mode)
1282 || (MODE_N1(pd->mode) && !pref_n1_cw_extend_cw_length_with_rsvd)
1283 /* for N:1 add RSV only if it is NOT used in length */
1284 || ((pd->mode == PWATM_MODE_AAL5_SDU) && !pref_aal5_sdu_extend_cw_length_with_rsvd)
1285 /* for AAl5 SDU add RSV only if it is NOT used in length */)
1287 if (MODE_11_OR_AAL5_PDU(pd->mode))
1289 item = proto_tree_add_item(tree
1290 ,hf_generic_cw_rsv, tvb, 0, 1, FALSE);
1294 item = proto_tree_add_item(tree
1295 ,hf_pref_cw_rsv, tvb, 1, 1, FALSE);
1298 if (pd->props & PWC_CW_BAD_RSV)
1300 expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR
1301 ,"Reserved bits in Control Word must be 0");
1305 PROTO_ITEM_SET_HIDDEN(item); /*...and show only in error cases */
1310 if (MODE_N1(pd->mode)
1311 || (PWATM_MODE_AAL5_SDU == pd->mode))
1314 int hf_len = hf_pref_cw_len;
1315 if (MODE_N1(pd->mode))
1317 if (pref_n1_cw_extend_cw_length_with_rsvd)
1318 hf_len = hf_pref_cw_rsvlen;
1320 else /*PW_MODE_AAL5_SDU*/
1322 if (pref_aal5_sdu_extend_cw_length_with_rsvd)
1323 hf_len = hf_pref_cw_rsvlen;
1325 item = proto_tree_add_item(tree, hf_len, tvb, 1, 1, FALSE);
1327 if (pd->props & PWC_CW_BAD_LEN_MUST_BE_0)
1329 expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR
1330 ,"Bad Length: must be 0 for this encapsulation");
1332 if (pd->props & PWC_CW_BAD_PAYLEN_LE_0)
1334 expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR
1335 ,"Bad Length: too small, must be >= %d"
1336 ,(int)(PWC_SIZEOF_CW+SIZEOF_N1_PW_CELL));
1338 if (pd->props & PWC_CW_BAD_PAYLEN_GT_PACKET)
1340 expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR
1341 ,"Bad Length: must be <= than PSN packet size (%d)"
1342 ,(int)pd->packet_size);
1344 if (pd->props & PWC_CW_BAD_PADDING_NE_0)
1346 expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR
1347 ,"Bad Length: must be == PSN packet size (%d), no padding allowed"
1348 ,(int)pd->packet_size);
1352 /* sequence number */
1353 (void)proto_tree_add_item(tree, hf_cw_seq, tvb
1354 ,MODE_11_OR_AAL5_PDU(pd->mode) ? 1 : 2, 2, FALSE);
1356 /* atm-specific byte */
1357 if (MODE_11(pd->mode))
1359 (void) proto_tree_add_item(tree, hf_gen_cw_atmbyte, tvb, 3, 1, FALSE);
1361 * no need to highlight item in the tree, therefore
1362 * expert_add_info_format() is not used here.
1364 item = proto_tree_add_text(tree,tvb,3,1
1365 ,"ATM-specific byte of CW is fully dissected below as %s%s"
1366 ,(PWATM_MODE_11_VPC == pd->mode) ? "a part of " : ""
1367 ,"PW ATM Cell Header [000]");
1368 PROTO_ITEM_SET_GENERATED(item);
1370 * Note: if atm-specific byte contains something wrong
1371 * (e.g. non-zero RSV or inadequate V), CW is not
1377 if (PWATM_MODE_AAL5_PDU == pd->mode)
1380 tvb_2 = tvb_new_subset(tvb, (PWC_SIZEOF_CW-1), -1, -1);
1381 call_dissector(dh_cell_header, tvb_2, pinfo, tree);
1382 proto_item_append_text(item_top,", ");
1383 proto_item_append_text_cwb3_fields(item_top,pd);
1393 * This function is also used to dissect 3rd byte of CW in AAL5 PDU mode.
1396 int dissect_cell_header(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
1398 pwatm_private_data_t * pd;
1399 gboolean is_enough_data;
1402 pd = pinfo->private_data;
1403 DISSECTOR_ASSERT (NULL != pd);
1404 pd->vpi = pd->vci = pd->pti = -1;
1405 pd->cwb3.clp = pd->cwb3.m = pd->cwb3.v = pd->cwb3.rsv = pd->cwb3.u = pd->cwb3.e = -1;
1407 if (PWATM_MODE_AAL5_PDU == pd->mode)
1409 if (tvb_reported_length_remaining(tvb, 0) < 1)
1411 is_enough_data = FALSE;
1416 is_enough_data = TRUE;
1423 size = tvb_reported_length_remaining(tvb, 0);
1425 if (size < pw_cell_header_size(pd->mode,pd->submode))
1427 is_enough_data = FALSE;
1428 dissect_size = size;
1432 is_enough_data = TRUE;
1433 dissect_size = pw_cell_header_size(pd->mode,pd->submode);
1438 * NB: do not touch columns -- keep info from previous dissector
1441 /* Collect info for upper-level dissectors regardless of
1442 * the presence of the tree
1449 case PWATM_MODE_AAL5_SDU:
1450 DISSECTOR_ASSERT(pd->submode == PWATM_SUBMODE_ADMIN_CELL);
1451 /*fallthrough for ATM admin cell submode only*/
1452 case PWATM_MODE_N1_CW:
1453 case PWATM_MODE_N1_NOCW:
1454 pd->vpi = (tvb_get_ntohs (tvb, 0) >> 4);
1455 pd->vci = (tvb_get_ntoh24(tvb, 1) >> 4) & 0xffff;
1456 tmp8 = (tvb_get_guint8(tvb, 3));
1457 pd->pti = (tmp8 >> 1) & 0x07;
1458 pd->cwb3.clp = (tmp8 >> 0) & 0x01;
1459 UPDATE_CUMULATIVE_VALUE(pd->cumulative.vpi,pd->vpi);
1460 UPDATE_CUMULATIVE_VALUE(pd->cumulative.vci,pd->vci);
1461 UPDATE_CUMULATIVE_VALUE(pd->cumulative.pti,pd->pti);
1462 UPDATE_CUMULATIVE_VALUE(pd->cumulative.clp,pd->cwb3.clp);
1464 * OAM cell mode is always used for aal5_sdu/admin_cell mode,
1465 * even if pti indicates user cell.
1468 (pd->mode == PWATM_MODE_AAL5_SDU && pd->submode == PWATM_SUBMODE_ADMIN_CELL)
1469 || PTI_IS_ADMIN(pd->pti);
1471 case PWATM_MODE_11_VPC:
1472 pd->vci = tvb_get_ntohs(tvb, 1);
1473 UPDATE_CUMULATIVE_VALUE(pd->cumulative.vci,pd->vci);
1475 case PWATM_MODE_11_VCC:
1476 tmp8 = (tvb_get_guint8(tvb, 0));
1477 pd->cwb3.m = (tmp8 >> 7) & 0x1;
1478 pd->cwb3.v = (tmp8 >> 6) & 0x1;
1479 pd->cwb3.rsv = (tmp8 >> 4) & 0x3;
1480 pd->pti = (tmp8 >> 1) & 0x7;
1481 pd->cwb3.clp = (tmp8 >> 0) & 0x1;
1482 UPDATE_CUMULATIVE_VALUE(pd->cumulative.pti,pd->pti);
1483 UPDATE_CUMULATIVE_VALUE(pd->cumulative.clp,pd->cwb3.clp);
1485 * OAM cell mode is possible if packet contains atm cell (m == 0).
1487 pd->cell_mode_oam = PTI_IS_ADMIN(pd->pti) && (pd->cwb3.m == 0);
1489 case PWATM_MODE_AAL5_PDU:
1490 tmp8 = (tvb_get_guint8(tvb, 0));
1491 pd->cwb3.m = (tmp8 >> 7) & 0x1;
1492 pd->cwb3.v = (tmp8 >> 6) & 0x1;
1493 pd->cwb3.rsv = (tmp8 >> 3) & 0x7;
1494 pd->cwb3.u = (tmp8 >> 2) & 0x1;
1495 pd->cwb3.e = (tmp8 >> 1) & 0x1;
1496 pd->cwb3.clp = (tmp8 >> 0) & 0x1;
1497 UPDATE_CUMULATIVE_VALUE(pd->cumulative.clp,pd->cwb3.clp);
1500 DISSECTOR_ASSERT_NOT_REACHED();
1509 item = proto_tree_add_item(tree, proto_cell_header, tvb
1513 if (PWATM_MODE_AAL5_PDU == pd->mode)
1515 proto_item_set_text(item, "Third byte of Control Word"); /*overwrite heading line*/
1516 /* cwb3 fileds are appended to CW heading line, not here */
1520 proto_item_append_text(item," [%.3d]",pd->pw_cell_number);
1521 proto_item_append_text(item,", ");
1523 proto_item_append_text(item, "VPI:%.4u ", (unsigned)(pd->vpi));
1525 proto_item_append_text(item, "VCI:%.5u ", (unsigned)(pd->vci));
1527 proto_item_append_text(item, "PTI:%.1u ", (unsigned)(pd->pti));
1528 proto_item_append_text_cwb3_fields(item,pd);
1533 tree = proto_item_add_subtree(item, ett_cell_header);
1537 if (MODE_N1(pd->mode)
1538 || (pd->mode == PWATM_MODE_AAL5_SDU && pd->submode == PWATM_SUBMODE_ADMIN_CELL))
1540 (void) proto_tree_add_uint(tree, hf_cell_h_vpi, tvb, 0, 2, (unsigned)pd->vpi);
1541 (void) proto_tree_add_uint(tree, hf_cell_h_vci, tvb, 1, 3, (unsigned)pd->vci);
1543 item = proto_tree_add_item(tree, hf_cell_h_pti, tvb, 3, 1, FALSE);
1544 if (NULL == match_strval(pd->pti,atm_pt_vals))
1546 expert_add_info_format(pinfo, item, PI_UNDECODED, PI_WARN,
1547 "Unknown value of PTI field (%d) in the ATM cell header",
1550 else if (pd->mode == PWATM_MODE_AAL5_SDU && !PTI_IS_ADMIN(pd->pti))
1552 expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR,
1553 "ATM admin cell is transerred;"
1554 " PTI field (%d) should be 4, 5 or 6.",
1558 (void) proto_tree_add_item(tree, hf_cell_h_clp, tvb, 3, 1, FALSE);
1560 else if (MODE_11_OR_AAL5_PDU(pd->mode))
1562 item = proto_tree_add_item(tree, hf_cell_h_m , tvb, 0, 1, FALSE);
1563 if ((0 != pd->cwb3.m) && MODE_11(pd->mode))
1565 expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR
1567 " M bit must be 0 to distinguish from AAL5 PDU mode");
1570 item = proto_tree_add_item(tree, hf_cell_h_v , tvb, 0, 1, FALSE);
1571 if ((0 == pd->cwb3.v) && (PWATM_MODE_11_VPC == pd->mode))
1573 expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR
1575 " V bit must be 1 to indicate that VCI is present");
1577 if ((0 != pd->cwb3.v) && (PWATM_MODE_11_VCC == pd->mode))
1579 expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR
1581 " V bit must be 0 to indicate that VCI is absent");
1583 if ((0 != pd->cwb3.v) && (PWATM_MODE_AAL5_PDU == pd->mode))
1585 expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR
1587 " V bit must be 0 to indicate that VCI is absent");
1590 item = proto_tree_add_item(tree
1591 ,(PWATM_MODE_AAL5_PDU == pd->mode)
1595 if (0 != pd->cwb3.rsv)
1597 expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR
1598 ,"Reserved bits in the 3rd byte of CW must be 0");
1602 PROTO_ITEM_SET_HIDDEN(item); /*...and show only in error cases */
1605 if (MODE_11(pd->mode))
1607 item = proto_tree_add_item(tree, hf_cell_h_pti, tvb, 0, 1, FALSE);
1608 if (NULL == match_strval(pd->pti,atm_pt_vals))
1610 expert_add_info_format(pinfo, item, PI_UNDECODED, PI_WARN,
1611 "Unknown value of PTI field (%d) in the atm-specific byte"
1617 (void) proto_tree_add_item(tree, hf_aal5_pdu_u, tvb, 0, 1, FALSE);
1618 (void) proto_tree_add_item(tree, hf_aal5_pdu_e, tvb, 0, 1, FALSE);
1621 (void) proto_tree_add_item(tree, hf_cell_h_clp, tvb, 0, 1, FALSE);
1623 if (PWATM_MODE_11_VPC == pd->mode)
1625 (void) proto_tree_add_uint(tree, hf_cell_h_vci, tvb, 1, 2
1626 ,(unsigned)pd->vci);
1631 DISSECTOR_ASSERT_NOT_REACHED();
1636 expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR
1637 ,"Not enough data (size: %d), impossible to decode"
1638 ,(int)dissect_size);
1642 return dissect_size;
1647 int dissect_cell(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
1649 gboolean is_enough_data;
1654 size = tvb_reported_length_remaining(tvb, 0);
1655 if (size < SIZEOF_ATM_CELL_PAYLOAD)
1657 is_enough_data = FALSE;
1658 dissect_size = size;
1662 is_enough_data = TRUE;
1663 dissect_size = SIZEOF_ATM_CELL_PAYLOAD;
1668 * NB: do not touch columns -- keep info from previous dissector
1674 item = proto_tree_add_item(tree, proto_cell, tvb, 0, dissect_size, FALSE);
1676 pwatm_private_data_t * pd;
1677 pd = pinfo->private_data;
1680 proto_item_append_text(item," [%.3d]",pd->pw_cell_number);
1683 pwc_item_append_text_n_items(item,dissect_size,"byte");
1684 if (!is_enough_data)
1686 expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR
1687 ,"Bad length of cell payload: must be == %d"
1688 ,(int)SIZEOF_ATM_CELL_PAYLOAD);
1694 tree = proto_item_add_subtree(item, ett_cell);
1695 tvb_d = tvb_new_subset(tvb, 0, dissect_size, -1);
1696 call_dissector(dh_data, tvb_d, pinfo, tree);
1697 item = proto_tree_add_int(tree, hf_cell_payload_len, tvb, 0, 0, dissect_size);
1698 PROTO_ITEM_SET_HIDDEN(item);
1701 return dissect_size;
1705 void proto_register_pw_atm_ata(void)
1707 static const value_string clp_vals[] = {
1708 { 0, "High priority" },
1709 { 1, "Low priority" },
1712 static const value_string m_vals[] = {
1714 { 1, "AAL5 payload" },
1717 static const value_string u_vals[] = {
1718 { 0, "This frame does not contain the last cell of AAL5 PDU" },
1719 { 1, "This frame contains the last cell of AAL5 PDU" },
1722 static const value_string e_vals[] = {
1723 { 0, "Congestion is not experienced" },
1724 { 1, "Congestion is experienced for one or more ATM AAL5 cells" },
1727 static hf_register_info hfa_cell_header[] = {
1728 { &hf_cell_h_vpi ,{"VPI" ,"atm.vpi"
1729 ,FT_UINT16 ,BASE_DEC ,NULL ,0
1731 ,{ &hf_cell_h_vci ,{"VCI" ,"atm.vci"
1732 ,FT_UINT16 ,BASE_DEC ,NULL ,0
1734 ,{ &hf_cell_h_pti ,{"Payload Type" ,"atm.pti"
1735 ,FT_UINT8 ,BASE_DEC ,VALS(atm_pt_vals),0x0e
1736 ,"The 3-bit Payload Type Identifier (PTI) incorporates ATM Layer"
1737 " PTI coding of the cell. These bits are set to the value of the"
1738 " PTI of the encapsulated ATM cell."
1740 ,{ &hf_cell_h_clp ,{"Cell Loss Priority" ,"atm.clp"
1741 ,FT_UINT8 ,BASE_DEC ,VALS(clp_vals) ,0x01
1742 ,"The Cell Loss Priority (CLP) field indicates CLP value"
1743 " of the encapsulated cell."
1745 ,{ &hf_cell_h_m ,{"Transport Mode" ,"atm.pw_control_byte.m"
1746 ,FT_UINT8 ,BASE_DEC ,VALS(m_vals) ,0x80
1747 ,"Bit (M) of the control byte indicates whether the packet"
1748 " contains an ATM cell or a frame payload. If set to 0,"
1749 " the packet contains an ATM cell. If set to 1, the PDU"
1750 " contains an AAL5 payload."
1752 ,{ &hf_cell_h_v ,{"VCI Present" ,"atm.pw_control_byte.v"
1753 ,FT_BOOLEAN ,8 ,TFS(&tfs_yes_no),0x40
1754 ,"Bit (V) of the control byte indicates whether the VCI field"
1755 " is present in the packet. If set to 1, the VCI field is present"
1756 " for the cell. If set to 0, no VCI field is present."
1758 ,{ &hf_cell_h_rsv ,{"Reserved bits" ,"atm.pw_control_byte.rsv"
1759 ,FT_UINT8 ,BASE_DEC ,NULL ,0x30
1760 ,"The reserved bits should be set to 0 at the transmitter and"
1761 " ignored upon reception."
1763 ,{ &hf_aal5_pdu_rsv ,{"Reserved bits" ,"atm.pw_control_byte.rsv"
1764 ,FT_UINT8 ,BASE_DEC ,NULL ,0x38
1765 ,"The reserved bits should be set to 0 at the transmitter and"
1766 " ignored upon reception."
1768 ,{ &hf_aal5_pdu_u ,{"U bit" ,"atm.pw_control_byte.u"
1769 ,FT_UINT8 ,BASE_DEC ,VALS(u_vals) ,0x04
1770 ,"Indicates whether this frame contains the last cell of"
1771 " an AAL5 PDU and represents the value of the ATM User-to-User"
1772 " bit for the last ATM cell of the PSN frame. Note: The ATM"
1773 " User-to-User bit is the least significant bit of the PTI"
1774 " in the ATM header."
1776 ,{ &hf_aal5_pdu_e ,{"EFCI" ,"atm.pw_control_byte.efci"
1777 ,FT_UINT8 ,BASE_DEC ,VALS(e_vals) ,0x02
1778 ,"EFCI is set to the EFCI state of the last cell of the"
1779 " AAL5 PDU or AAL5 fragment. Note: The EFCI state is"
1780 " indicated in the middle bit of each ATM cell's PTI."
1783 static hf_register_info hfa_cell[] = {
1784 {&hf_cell_payload_len ,{"Length" ,"atm.cell.len"
1785 ,FT_INT32 ,BASE_DEC ,NULL ,0
1789 #define HF_INITIALIZER_NCELLS(hf_handle)\
1790 {&(hf_handle) ,{"Number of good encapsulated cells","pw.atm.cells"\
1791 ,FT_INT32 ,BASE_DEC ,NULL ,0\
1794 #define HF_INITIALIZER_PWTYPE(hf_handle,name)\
1795 { &hf_handle ,{name ,name\
1796 ,FT_BOOLEAN ,0 ,NULL ,0x0\
1797 ,"Identifies type of ATM PW. May be used for filtering.",HFILL}}
1800 static hf_register_info hfa_n1_nocw[] = {
1801 HF_INITIALIZER_NCELLS(hf_n1_nocw_ncells)
1802 ,HF_INITIALIZER_PWTYPE(hf_pw_type_n1_nocw,"pw.type.atm.n1nocw")
1805 static hf_register_info hfa_n1_cw[] = {
1806 HF_INITIALIZER_NCELLS(hf_n1_cw_ncells)
1807 ,HF_INITIALIZER_PWTYPE(hf_pw_type_n1_cw,"pw.type.atm.n1cw")
1810 static hf_register_info hfa_11_aal5pdu[] = {
1811 HF_INITIALIZER_NCELLS(hf_11_ncells)
1812 ,HF_INITIALIZER_PWTYPE(hf_pw_type_11_vcc,"pw.type.atm.11vcc")
1813 ,HF_INITIALIZER_PWTYPE(hf_pw_type_11_vpc,"pw.type.atm.11vpc")
1814 ,HF_INITIALIZER_PWTYPE(hf_pw_type_aal5_pdu,"pw.type.atm.aal5pdu")
1817 static hf_register_info hfa_aal5_sdu[] = {
1818 HF_INITIALIZER_PWTYPE(hf_pw_type_aal5_sdu,"pw.type.atm.aal5sdu")
1821 static const value_string a5s_t_vals[] = {
1822 { 0, "AAL5 payload" },
1823 { 1, "ATM admin cell" },
1827 static const value_string a5s_e_vals[] = {
1828 { 0, "No congestion" },
1829 { 1, "Congestion experienced" },
1833 static hf_register_info hfa_cw[] = {
1834 { &hf_cw_bits03 ,{"Bits 0 to 3" ,"pw.cw.bits03"
1835 ,FT_UINT8 ,BASE_HEX ,NULL ,0xf0
1837 ,{ &hf_pref_cw_flags ,{"Flags" ,"pw.cw.flags"
1838 ,FT_UINT8 ,BASE_HEX ,NULL ,0x0f
1840 ,{ &hf_pref_cw_a5s_t ,{"Payload type" ,"atm.pt"
1841 ,FT_UINT8 ,BASE_DEC ,VALS(a5s_t_vals),0x08
1842 ,"Bit (T) of the control word indicates whether the packet contains"
1843 " an ATM admin cell or an AAL5 payload. If T = 1, the packet"
1844 " contains an ATM admin cell, encapsulated according to the N:1"
1845 " cell relay encapsulation. If not set, the PDU"
1846 " contains an AAL5 payload."
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"
1856 ,{ &hf_pref_cw_a5s_c ,{"CLP bit" ,"atm.clp"
1857 ,FT_UINT8 ,BASE_DEC ,VALS(clp_vals) ,0x02
1858 ,"The ingress router sets this bit to 1 if the CLP bit"
1859 " of any of the ATM cells that transported the AAL5 CPCS-SDU is set"
1860 " to 1, or if the CLP bit of the single ATM cell to be transported"
1861 " in the packet is set to 1. Otherwise this bit is set to 0."
1863 ,{ &hf_pref_cw_a5s_u ,{"U bit (Command/Response)" ,"pw.cw.aal5sdu.u"
1864 ,FT_UINT8 ,BASE_DEC ,NULL ,0x01
1865 ,"When FRF.8.1 Frame Relay/ATM PVC Service Interworking [RFC3916]"
1866 " traffic is being transported, the Least-Significant Bit of CPCS-UU"
1867 " of the AAL5 CPCS-PDU may contain the Frame Relay C/R bit."
1868 " The ingress router copies this bit here."
1870 ,{ &hf_pref_cw_rsv ,{"Reserved bits" ,"pw.cw.rsv"
1871 ,FT_UINT8 ,BASE_DEC ,NULL ,0xc0
1873 ,{ &hf_generic_cw_rsv ,{"Reserved bits" ,"pw.cw.rsv"
1874 ,FT_UINT8 ,BASE_DEC ,NULL ,0x0f
1876 ,{ &hf_pref_cw_len ,{"Length" ,"pw.cw.length"
1877 ,FT_UINT8 ,BASE_DEC ,NULL ,0x3f
1879 ,{ &hf_pref_cw_rsvlen ,{"Length (extended)" ,"pw.cw.length"
1880 ,FT_UINT8 ,BASE_DEC ,NULL ,0xff
1882 ,{ &hf_cw_seq ,{"Sequence number" ,"pw.cw.seqno"
1883 ,FT_UINT16 ,BASE_DEC ,NULL ,0
1885 ,{ &hf_gen_cw_atmbyte ,{"ATM-specific byte" ,"pw.cw.3rd_byte"
1886 ,FT_UINT8 ,BASE_HEX ,NULL ,0xFF
1889 static gint *ett_array[] = {
1897 proto_register_protocol(pwc_longname_pw_atm_n1_cw
1900 proto_11_or_aal5_pdu =
1901 proto_register_protocol(pwc_longname_pw_atm_11_or_aal5_pdu
1902 ,shortname_11_or_aal5_pdu
1903 ,"mplspwatm11_or_aal5pdu");
1905 proto_register_protocol(pwc_longname_pw_atm_aal5_sdu
1907 ,"mplspwatmaal5sdu");
1909 proto_register_protocol(pwc_longname_pw_atm_n1_nocw
1911 ,"mplspwatmn1nocw");
1912 proto_control_word =
1913 proto_register_protocol("MPLS PW ATM Control Word"
1914 ,"MPLS PW ATM Control Word"
1915 ,"mplspwatmcontrolword");
1917 proto_register_protocol("MPLS PW ATM Cell Header"
1918 ,"MPLS PW ATM Cell Header"
1919 ,"mplspwatmcellheader");
1921 proto_register_protocol("ATM Cell"
1925 proto_register_field_array( proto_cell ,hfa_cell ,array_length(hfa_cell));
1926 proto_register_field_array( proto_cell_header ,hfa_cell_header,array_length(hfa_cell_header));
1927 proto_register_field_array( proto_control_word ,hfa_cw ,array_length(hfa_cw));
1928 proto_register_field_array( proto_n1_nocw ,hfa_n1_nocw ,array_length(hfa_n1_nocw));
1929 proto_register_field_array( proto_n1_cw ,hfa_n1_cw ,array_length(hfa_n1_cw));
1930 proto_register_field_array( proto_11_or_aal5_pdu ,hfa_11_aal5pdu ,array_length(hfa_11_aal5pdu));
1931 proto_register_field_array( proto_aal5_sdu ,hfa_aal5_sdu ,array_length(hfa_aal5_sdu));
1933 proto_register_subtree_array(ett_array, array_length(ett_array));
1935 register_dissector("mpls_pw_atm_aal5_sdu" ,dissect_aal5_sdu ,proto_aal5_sdu);
1936 register_dissector("mpls_pw_atm_11_or_aal5_pdu" ,dissect_11_or_aal5_pdu ,proto_11_or_aal5_pdu);
1937 register_dissector("mpls_pw_atm_n1_cw" ,dissect_n1_cw ,proto_n1_cw);
1938 register_dissector("mpls_pw_atm_n1_nocw" ,dissect_n1_nocw ,proto_n1_nocw);
1939 register_dissector("mpls_pw_atm_control_word" ,dissect_control_word ,proto_control_word);
1940 new_register_dissector("mpls_pw_atm_cell" ,dissect_cell ,proto_cell);
1941 new_register_dissector("mpls_pw_atm_cell_header",dissect_cell_header ,proto_cell_header);
1943 static const char description_allow_cw_length_nonzero[] =
1944 "Enable to allow non-zero Length in Control Word."
1945 " This may be needed to correctly decode traffic from some legacy devices"
1946 " which generate non-zero Length even if there is no padding in the packet."
1947 " Note that Length should have proper value (dissector checks this anyway)."
1949 "Disable to blame all packets with CW.Length <> 0. This conforms to RFC4717."
1951 static const char description_extend_cw_length_with_rsvd[] =
1952 "Enable to use reserved bits (8..9) of Control Word as an extension of CW.Length."
1953 " This may be needed to correctly decode traffic from some legacy devices"
1954 " which uses reserved bits as extension of Length"
1956 "Disable to blame all packets with CW.Reserved <> 0. This conforms to RFC4717."
1958 module_t * module_n1_cw;
1959 module_t * module_aal5_sdu;
1961 module_n1_cw = prefs_register_protocol(proto_n1_cw,NULL);
1962 prefs_register_bool_preference(module_n1_cw
1963 ,"allow_cw_length_nonzero"
1964 ,"Allow CW.Length <> 0"
1965 ,&description_allow_cw_length_nonzero[0]
1966 ,&pref_n1_cw_allow_cw_length_nonzero);
1967 prefs_register_bool_preference(module_n1_cw
1968 ,"extend_cw_length_with_rsvd"
1969 ,"Use CW.Reserved as extension of CW.Length"
1970 ,&description_extend_cw_length_with_rsvd[0]
1971 ,&pref_n1_cw_extend_cw_length_with_rsvd);
1973 module_aal5_sdu = prefs_register_protocol(proto_aal5_sdu,NULL);
1974 prefs_register_bool_preference(module_aal5_sdu
1975 ,"allow_cw_length_nonzero_aal5"
1976 ,"Allow CW.Length <> 0"
1977 ,&description_allow_cw_length_nonzero[0]
1978 ,&pref_aal5_sdu_allow_cw_length_nonzero);
1979 prefs_register_bool_preference(module_aal5_sdu
1980 ,"extend_cw_length_with_rsvd_aal5"
1981 ,"Use CW.Reserved as extension of CW.Length"
1982 ,&description_extend_cw_length_with_rsvd[0]
1983 ,&pref_aal5_sdu_extend_cw_length_with_rsvd);
1988 void proto_reg_handoff_pw_atm_ata(void)
1990 dissector_handle_t h;
1991 h = find_dissector("mpls_pw_atm_n1_cw");
1992 dissector_add( "mpls.label", LABEL_INVALID, h );
1993 h = find_dissector("mpls_pw_atm_n1_nocw");
1994 dissector_add( "mpls.label", LABEL_INVALID, h );
1995 h = find_dissector("mpls_pw_atm_11_or_aal5_pdu");
1996 dissector_add( "mpls.label", LABEL_INVALID, h );
1997 h = find_dissector("mpls_pw_atm_aal5_sdu");
1998 dissector_add( "mpls.label", LABEL_INVALID, h );
2000 dh_cell = find_dissector("mpls_pw_atm_cell");
2001 dh_cell_header = find_dissector("mpls_pw_atm_cell_header");
2002 dh_control_word = find_dissector("mpls_pw_atm_control_word");
2003 dh_atm_truncated = find_dissector("atm_truncated");
2004 dh_atm_untruncated = find_dissector("atm_untruncated");
2005 dh_atm_oam_cell = find_dissector("atm_oam_cell");
2006 dh_padding = find_dissector("pw_padding");
2007 dh_data = find_dissector("data");