MSWSP: add two more Property Sets
[wireshark-wip.git] / epan / dissectors / packet-pw-atm.c
blob605559613b77c1988d9336c0f523704b14f6bfe2
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 * $Id$
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
31 DONE:
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
35 - ATM AAL5 SDU Mode
36 - ATM AAL5 PDU Mode
39 #include "config.h"
41 #include <glib.h>
42 #include <epan/packet.h>
43 #include <epan/expert.h>
44 #include <epan/prefs.h>
46 #include <wiretap/wtap.h> /*for atm pseudo header*/
47 #include "packet-mpls.h"
48 #include "packet-atm.h"
49 #include "packet-pw-atm.h"
50 #include "packet-pw-common.h"
52 static gint proto_n1_nocw = -1;
53 static gint proto_n1_cw = -1;
54 static gint proto_11_or_aal5_pdu = -1;
55 static gint proto_aal5_sdu = -1;
56 /* subordinate dissectors: */
57 static gint proto_control_word = -1;
58 static gint proto_cell_header = -1;
59 static gint proto_cell = -1;
61 static gint ett_encaps = -1;
62 static gint ett_cw = -1;
63 static gint ett_cell_header = -1;
64 static gint ett_cell = -1;
66 static int hf_pw_type_n1_cw = -1;
67 static int hf_pw_type_n1_nocw = -1;
68 static int hf_pw_type_11_vcc = -1;
69 static int hf_pw_type_11_vpc = -1;
70 static int hf_pw_type_aal5_sdu = -1;
71 static int hf_pw_type_aal5_pdu = -1;
73 static int hf_cell_h_vpi = -1;
74 static int hf_cell_h_vci = -1;
75 static int hf_cell_h_pti = -1;
76 static int hf_cell_h_clp = -1;
77 static int hf_cell_h_m = -1;
78 static int hf_cell_h_v = -1;
79 static int hf_cell_h_rsv = -1;
80 static int hf_aal5_pdu_rsv = -1;
81 static int hf_aal5_pdu_u = -1;
82 static int hf_aal5_pdu_e = -1;
84 static int hf_cw_bits03 = -1;
85 static int hf_pref_cw_rsv = -1;
86 static int hf_generic_cw_rsv = -1;
87 static int hf_pref_cw_flags = -1;
88 static int hf_pref_cw_a5s_t = -1;
89 static int hf_pref_cw_a5s_e = -1;
90 static int hf_pref_cw_a5s_c = -1;
91 static int hf_pref_cw_a5s_u = -1;
92 static int hf_pref_cw_len = -1;
93 static int hf_pref_cw_rsvlen = -1;
94 static int hf_cw_seq = -1;
95 static int hf_n1_cw_ncells = -1;
96 static int hf_n1_nocw_ncells = -1;
97 static int hf_11_ncells = -1;
98 static int hf_gen_cw_atmbyte = -1;
99 static int hf_cell_payload_len = -1;
101 static expert_field ei_cell_h_v_not_one = EI_INIT;
102 static expert_field ei_cell_h_pti_undecoded = EI_INIT;
103 static expert_field ei_pref_cw_flags = EI_INIT;
104 static expert_field ei_cell_h_v_not_zero = EI_INIT;
105 static expert_field ei_pw_payload_size_invalid_note = EI_INIT;
106 static expert_field ei_pw_payload_size_invalid_error = EI_INIT;
107 static expert_field ei_cell_h_pti_malformed = EI_INIT;
108 static expert_field ei_cell_h_rsv = EI_INIT;
109 static expert_field ei_cell_broken = EI_INIT;
110 static expert_field ei_cell_h_m = EI_INIT;
111 static expert_field ei_cw_bits03 = EI_INIT;
112 static expert_field ei_pw_packet_size_too_small = EI_INIT;
113 static expert_field ei_pref_cw_len = EI_INIT;
115 static dissector_handle_t dh_cell;
116 static dissector_handle_t dh_cell_header;
117 static dissector_handle_t dh_control_word;
118 static dissector_handle_t dh_atm_truncated;
119 static dissector_handle_t dh_atm_untruncated;
120 static dissector_handle_t dh_atm_oam_cell;
121 static dissector_handle_t dh_padding;
122 static dissector_handle_t dh_data;
124 #define PTI_IS_ADMIN(pti) ((pti) == 4 || (pti) == 5 || (pti) == 6) /*see atm_pt_vals[]*/
126 #define MODE_11(mode) (PWATM_MODE_11_VCC == (mode) || PWATM_MODE_11_VPC == (mode))
127 #define MODE_N1(mode) (PWATM_MODE_N1_NOCW == (mode)|| PWATM_MODE_N1_CW == (mode))
128 #define MODE_11_OR_AAL5_PDU(mode) (MODE_11(mode) || PWATM_MODE_AAL5_PDU == (mode))
130 #define VALUE_SELECTOR_VPC_VCC_PDU(mode,val_vpc,val_vcc,val_pdu)\
131 ((PWATM_MODE_11_VPC == (mode)) \
132 ? (val_vpc) \
133 : ((PWATM_MODE_11_VCC == (mode)) \
134 ? (val_vcc) \
135 : ((PWATM_MODE_AAL5_PDU == (mode)) \
136 ? (val_pdu) \
137 : 0 \
142 #define UPDATE_CUMULATIVE_VALUE(cumulative_val,new_val)\
145 if (-2 >= (cumulative_val))\
148 else if (-1 == (cumulative_val))\
150 (cumulative_val) = (new_val);\
152 else if ((new_val) != (cumulative_val))\
154 (cumulative_val) = -2;\
157 while(0)
159 #define SIZEOF_ATM_CELL_PAYLOAD 48
160 #define SIZEOF_N1_PW_CELL_HEADER 4
161 #define SIZEOF_11_VCC_PW_CELL_HEADER 1
162 #define SIZEOF_11_VPC_PW_CELL_HEADER 3
163 #define SIZEOF_N1_PW_CELL (SIZEOF_ATM_CELL_PAYLOAD+SIZEOF_N1_PW_CELL_HEADER)
164 #define SIZEOF_11_VCC_PW_CELL (SIZEOF_ATM_CELL_PAYLOAD+SIZEOF_11_VCC_PW_CELL_HEADER)
165 #define SIZEOF_11_VPC_PW_CELL (SIZEOF_ATM_CELL_PAYLOAD+SIZEOF_11_VPC_PW_CELL_HEADER)
167 const char pwc_longname_pw_atm_n1_cw[] = "MPLS PW ATM N-to-One encapsulation, with CW";
168 const char pwc_longname_pw_atm_n1_nocw[] = "MPLS PW ATM N-to-One encapsulation, no CW";
169 const char pwc_longname_pw_atm_11_or_aal5_pdu[] = "MPLS PW ATM One-to-One or AAL5 PDU encapsulation";
170 const char pwc_longname_pw_atm_aal5_sdu[] = "MPLS PW ATM AAL5 CPCS-SDU mode encapsulation";
172 static const char longname_pw_atm_11_vcc[] = "MPLS PW ATM One-to-One VCC Cell Transport";
173 static const char longname_pw_atm_11_vpc[] = "MPLS PW ATM One-to-One VPC Cell Transport";
174 static const char longname_pw_atm_aal5_pdu[] = "MPLS PW ATM AAL5 PDU encapsulation";
176 static const char shortname_n1_cw[] = "MPLS PW ATM N:1 CW";
177 static const char shortname_n1_nocw[] = "MPLS PW ATM N:1 no CW";
178 static const char shortname_11_or_aal5_pdu[] = "MPLS PW ATM 1:1 / AAL5 PDU";
179 static const char shortname_11_vpc[] = "MPLS PW ATM 1:1 VPC";
180 static const char shortname_11_vcc[] = "MPLS PW ATM 1:1 VCC";
181 static const char shortname_aal5_sdu[] = "MPLS PW ATM AAL5 SDU";
182 static const char shortname_aal5_pdu[] = "MPLS PW ATM AAL5 PDU";
185 * These options are needed to support Nokia AXE and stuff alike.
186 * Note that these options will affect PW type auto-guessing, if such heuristic
187 * implemented in the future.
189 static gboolean pref_n1_cw_allow_cw_length_nonzero = FALSE;
190 static gboolean pref_n1_cw_extend_cw_length_with_rsvd = FALSE;
191 static gboolean pref_aal5_sdu_allow_cw_length_nonzero = FALSE;
192 static gboolean pref_aal5_sdu_extend_cw_length_with_rsvd = FALSE;
195 static int
196 pw_cell_size(const pwatm_mode_t mode, const pwatm_submode_t submode)
198 switch (mode)
200 case PWATM_MODE_N1_NOCW:
201 case PWATM_MODE_N1_CW:
202 return SIZEOF_N1_PW_CELL;
203 case PWATM_MODE_11_VCC:
204 return SIZEOF_11_VCC_PW_CELL;
205 case PWATM_MODE_11_VPC:
206 return SIZEOF_11_VPC_PW_CELL;
207 case PWATM_MODE_AAL5_PDU:
208 /* AAL5 PDU size is n*48 bytes */
209 return SIZEOF_ATM_CELL_PAYLOAD;
210 case PWATM_MODE_AAL5_SDU:
211 if (PWATM_SUBMODE_ADMIN_CELL == submode)
213 return SIZEOF_N1_PW_CELL; /*n:1 encapsulation is used for admin cells*/
215 else
217 DISSECTOR_ASSERT_NOT_REACHED();
218 return 0;
220 default:
221 DISSECTOR_ASSERT_NOT_REACHED();
222 return 0;
226 static int
227 pw_cell_header_size(const pwatm_mode_t mode, const pwatm_submode_t submode)
229 switch (mode)
231 case PWATM_MODE_N1_NOCW:
232 case PWATM_MODE_N1_CW:
233 return SIZEOF_N1_PW_CELL_HEADER;
234 case PWATM_MODE_11_VCC:
235 return SIZEOF_11_VCC_PW_CELL_HEADER;
236 case PWATM_MODE_11_VPC:
237 return SIZEOF_11_VPC_PW_CELL_HEADER;
238 case PWATM_MODE_AAL5_SDU:
239 if (PWATM_SUBMODE_ADMIN_CELL == submode)
241 return SIZEOF_N1_PW_CELL_HEADER; /*n:1 encapsulation is used for admin cells*/
243 else
245 DISSECTOR_ASSERT_NOT_REACHED();
246 return 0;
248 case PWATM_MODE_AAL5_PDU: /*not applicable*/
249 default:
250 DISSECTOR_ASSERT_NOT_REACHED();
251 return 0;
255 static int
256 number_of_cells(const pwatm_mode_t mode
257 ,const pwatm_submode_t submode
258 ,const gint payload_size
259 ,gint* const remainder_size)
261 int cells;
263 DISSECTOR_ASSERT(payload_size >= 0);
265 switch (mode)
267 case PWATM_MODE_N1_NOCW:
268 case PWATM_MODE_N1_CW:
269 case PWATM_MODE_11_VCC:
270 case PWATM_MODE_11_VPC:
271 case PWATM_MODE_AAL5_PDU:
272 cells = payload_size / pw_cell_size(mode, submode);
273 *remainder_size = payload_size - (cells * pw_cell_size(mode, submode));
274 return cells;
275 case PWATM_MODE_AAL5_SDU:
276 if (PWATM_SUBMODE_ADMIN_CELL == submode)
278 cells = payload_size / pw_cell_size(mode, submode);
279 if (cells > 1) cells = 1; /*max. 1 admin cell may be present in aal5 sdu mode */
280 *remainder_size = payload_size - (cells * pw_cell_size(mode, submode));
281 return cells;
283 else
285 /*not applicable*/
287 /*fallthrough*/
288 default:
289 DISSECTOR_ASSERT_NOT_REACHED();
290 *remainder_size = payload_size;
291 return 0;
297 static void
298 col_append_pw_info(packet_info * pinfo
299 ,const int payload_size
300 ,const int cells
301 ,const int padding_size
302 ,pwatm_private_data_t * pd)
304 if (pd->props & PWC_ANYOF_CW_BAD)
306 col_append_str(pinfo->cinfo, COL_INFO, "CW:Bad");
309 if (pd->props & PWC_PAY_SIZE_BAD)
311 if (pd->props & PWC_ANYOF_CW_BAD)
313 col_append_str(pinfo->cinfo, COL_INFO, ", ");
315 col_append_str(pinfo->cinfo, COL_INFO, "Payload size:Bad, ");
316 col_append_fstr(pinfo->cinfo, COL_INFO, "%d byte%s"
317 ,(int)payload_size
318 ,plurality(payload_size, "", "s"));
321 if (pd->props == 0) /*omit "atm cells" etc if something is wrong*/
323 /* number of cells may be not known */
324 if (cells >=0)
325 col_append_fstr(pinfo->cinfo, COL_INFO, "%d ATM cell%s"
326 ,cells
327 ,plurality(cells, "", "s"));
329 * Display ATM-specific attributes which are the same
330 * across all the cells in the pw packet.
331 * Meanings of values:
332 * (-1) unknown - not displayed,
333 * (-2) "not the same in all cells" - not displayed
334 * positive values - ok, displayed
336 if (pd->cumulative.vpi >= 0)
337 col_append_fstr(pinfo->cinfo, COL_INFO, ", VPI:%.4d", pd->cumulative.vpi);
338 if (pd->cumulative.vci >= 0)
339 col_append_fstr(pinfo->cinfo, COL_INFO, ", VCI:%.5d", pd->cumulative.vci);
340 if (pd->cumulative.pti >= 0)
341 col_append_fstr(pinfo->cinfo, COL_INFO, ", PTI:%.1d", pd->cumulative.pti);
342 if (pd->cumulative.clp >= 0)
343 col_append_fstr(pinfo->cinfo, COL_INFO, ", CLP:%.1d", pd->cumulative.clp);
346 if (padding_size != 0)
348 col_append_fstr(pinfo->cinfo, COL_INFO, ", %d padding"
349 ,(int)padding_size);
354 static void
355 prepare_pseudo_header_atm(
356 union wtap_pseudo_header * const ph,
357 const pwatm_private_data_t * const pdata,
358 const guint aal)
360 DISSECTOR_ASSERT(NULL != pdata);
361 DISSECTOR_ASSERT(NULL != ph);
363 memset(ph, 0 , sizeof(*ph)); /* it is OK to clear unknown values */
364 ph->atm.flags = 0; /* status flags */
365 ph->atm.aal = aal;
366 ph->atm.type = TRAF_UNKNOWN;
367 ph->atm.subtype = TRAF_ST_UNKNOWN;
368 ph->atm.vpi = (pdata->vpi >= 0) ? pdata->vpi : 0 /*unknown*/;
369 ph->atm.vci = (pdata->vci >= 0) ? pdata->vci : 0 /*unknown*/;
370 ph->atm.aal2_cid = 0; /*not applicable*//* channel id */
371 ph->atm.channel = 0; /*unknown*//* link: 0 for DTE->DCE, 1 for DCE->DTE */
372 ph->atm.cells = 0; /*zero indicates that we do not have trailer info*/
373 /*user-to-user indicator & CPI*/
374 ph->atm.aal5t_u2u = 0; /* all bits unknown except lsb of UU */
375 if (pdata->aal5_sdu_frame_relay_cr_bit)
376 { /* Let's give Frame Relay C/R bit to ATM dissector.*/
377 ph->atm.aal5t_u2u |= (1<<8); /*UU octet is at << 8 in aal5t_u2u*/
379 ph->atm.aal5t_len = 0; /*unknown*//* length of the packet from trailer*/
380 ph->atm.aal5t_chksum = 0; /*unknown*//* checksum for AAL5 packet from trailer */
381 return;
385 static void
386 dissect_payload_and_padding(
387 tvbuff_t * tvb
388 ,packet_info * pinfo
389 ,proto_tree * tree
390 ,const gint payload_size
391 ,const gint padding_size
392 ,pwatm_private_data_t * pd)
394 int dissected;
395 tvbuff_t * tvb_2;
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_with_data(dh_cell_header, tvb_2, pinfo, tree, pd);
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;
419 tvbuff_t* tvb_3;
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;
425 else
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_with_data(dh_atm_oam_cell, tvb_3, pinfo, tree, pd);
439 dissected += bytes_to_dissect;
440 /* restore pseudo header */
441 pinfo->pseudo_header = pseudo_header_save;
443 else
445 dissected += call_dissector(dh_cell, tvb_2, pinfo, tree);
449 if (padding_size != 0)
451 tvb_2 = tvb_new_subset_remaining(tvb, -padding_size);
452 call_dissector(dh_padding, tvb_2, pinfo, tree);
454 return;
458 static gboolean
459 too_small_packet_or_notpw(tvbuff_t * tvb
460 ,packet_info * pinfo
461 ,proto_tree * tree
462 ,const int proto_handler
463 ,const char * const proto_name_column)
465 gint packet_size;
466 packet_size = tvb_reported_length_remaining(tvb, 0);
468 * FIXME
469 * "4" below should be replaced by something like "min_packet_size_this_dissector"
470 * Also call to dissect_try_cw_first_nibble() should be moved before this block
472 if (packet_size < 4) /* 4 is smallest size which may be sensible (for PWACH dissector) */
474 proto_item * item;
475 item = proto_tree_add_item(tree, proto_handler, tvb, 0, -1, ENC_NA);
476 expert_add_info_format(pinfo, item, &ei_pw_packet_size_too_small,
477 "PW packet size (%d) is too small to carry sensible information"
478 ,(int)packet_size);
479 /* represent problems in the Packet List pane */
480 col_set_str(pinfo->cinfo, COL_PROTOCOL, proto_name_column);
481 col_set_str(pinfo->cinfo, COL_INFO, "Malformed: PW packet is too small");
482 return TRUE;
484 if (dissect_try_cw_first_nibble(tvb, pinfo, tree))
486 return TRUE;
488 return FALSE;
493 * NOTE. RFC describes ATM-specific byte in a cumbersome way.
494 * It is a part of CW, but at the same time, it must be repeated
495 * with each cell, _except_ first.
497 * Alternatively, ATM-specific byte may be considered as part of
498 * PW payload (i.e., as part of pw atm cell header), so we can say that
499 * it is being repeated with each cell.
501 * This dissector is written according to the latter consideration.
503 static void
504 dissect_11_or_aal5_pdu(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
506 const char * proto_name_column;
507 const char * proto_name_tree = NULL;
508 gint payload_size;
509 int cells;
510 pwatm_private_data_t pd = PWATM_PRIVATE_DATA_T_INITIALIZER;
512 proto_name_column = &shortname_11_or_aal5_pdu[0];
513 if (too_small_packet_or_notpw(tvb, pinfo, tree, proto_11_or_aal5_pdu, proto_name_column))
515 return;
517 pd.packet_size = tvb_reported_length_remaining(tvb, 0);
520 * Guess encapsulation mode according to M & V bits from the 3rd byte of CW.
521 * Also adjust protocol name strings.
524 guint8 third_byte;
525 third_byte = tvb_get_guint8(tvb, 3);
526 if (0 == (third_byte & 0x80 /*generic_cw.m*/))
527 { /*1:1 modes*/
528 if (0 != (third_byte & 0x40 /*generic_cw.v*/))
530 pd.mode = PWATM_MODE_11_VPC;
531 proto_name_column = &shortname_11_vpc[0];
532 proto_name_tree = &longname_pw_atm_11_vpc[0];
534 else
536 pd.mode = PWATM_MODE_11_VCC;
537 proto_name_column = &shortname_11_vcc[0];
538 proto_name_tree = &longname_pw_atm_11_vcc[0];
541 else
543 pd.mode = PWATM_MODE_AAL5_PDU;
544 proto_name_column = &shortname_aal5_pdu[0];
545 proto_name_tree = &longname_pw_atm_aal5_pdu[0];
550 /* check how "good" is this packet */
551 pd.props = PWC_PACKET_PROPERTIES_T_INITIALIZER;
552 if (0 != (tvb_get_guint8(tvb, 0) & 0xf0 /*bits03*/))
554 pd.props |= PWC_CW_BAD_BITS03;
556 if (0 != (tvb_get_guint8(tvb, 0) & 0x0f /*generic_cw.rsvd*/))
558 pd.props |= PWC_CW_BAD_RSV;
562 * Do not dissect and validate atm-specific byte (3rd byte of CW).
563 * It will be dissected/validated as pw cell header.
567 * Decide about payload length and padding.
569 * Is padding allowed?
570 * eth header length == 14
571 * mpls label length == 4
572 * cw length == 4
573 * min payload length == 48
574 * => 14 + 4 + 4 + 48 == 70
575 * => 70 >= 64
576 * => no padding allowed
578 if (MODE_11(pd.mode))
580 gint bad_padding_size;
581 payload_size = pd.packet_size - (PWC_SIZEOF_CW-1);
582 cells = number_of_cells(pd.mode, pd.submode, payload_size, &bad_padding_size);
583 if ((0 == cells) || (0 != bad_padding_size))
585 pd.props |= PWC_PAY_SIZE_BAD;
588 else
589 { /*aal5_pdu mode*/
590 gint bad_padding_size;
591 payload_size = pd.packet_size - PWC_SIZEOF_CW;
592 cells = number_of_cells(pd.mode, pd.submode, payload_size, &bad_padding_size);
593 /* at least 1 cell must be present in the packet in this mode*/
594 if ((1 > cells) || (0 != bad_padding_size))
596 pd.props |= PWC_PAY_SIZE_BAD;
598 cells = -1; /*this value not needed anymore, suppress pinting of it*/
601 if (PWATM_MODE_AAL5_PDU == pd.mode)
603 /* sub-dissectors _may_ overwrite columns in aal5_pdu mode */
604 col_set_str(pinfo->cinfo, COL_PROTOCOL, proto_name_column);
605 col_clear(pinfo->cinfo, COL_INFO);
606 col_append_pw_info(pinfo, payload_size, cells, 0, &pd);
610 proto_item* item;
611 item = proto_tree_add_item(tree, proto_11_or_aal5_pdu, tvb, 0, -1, ENC_NA);
612 /*overwrite heading line*/
613 proto_item_set_text(item, proto_name_tree, 0/*-warn gcc 3.4.4*/);
614 pwc_item_append_text_n_items(item, cells, "good ATM cell");
616 proto_tree* tree2;
617 tree2 = proto_item_add_subtree(item, ett_encaps);
619 proto_item* item2;
620 item2 = proto_tree_add_boolean(tree2
621 ,VALUE_SELECTOR_VPC_VCC_PDU(pd.mode
622 ,hf_pw_type_11_vpc
623 ,hf_pw_type_11_vcc
624 ,hf_pw_type_aal5_pdu)
625 ,tvb, 0, 0, TRUE);
626 PROTO_ITEM_SET_GENERATED(item2);
627 if (MODE_11(pd.mode))
629 item2 = proto_tree_add_int(tree2, hf_11_ncells, tvb, 0, 0, cells);
630 PROTO_ITEM_SET_GENERATED(item2);
634 if (pd.props & PWC_PAY_SIZE_BAD)
636 expert_add_info_format(pinfo, item, &ei_pw_payload_size_invalid_error,
637 "PW payload size (%d) must be <> 0 and multiple of %d",
638 (int)payload_size, pw_cell_size(pd.mode, pd.submode));
639 if ((payload_size != 0) && MODE_11(pd.mode))
641 expert_add_info_format(pinfo, item, &ei_cell_broken,
642 "PW ATM cell [%.3d] is broken", (int)cells);
648 tvbuff_t* tvb_2;
649 tvb_2 = tvb_new_subset(tvb, 0, PWC_SIZEOF_CW, PWC_SIZEOF_CW);
650 call_dissector_with_data(dh_control_word, tvb_2, pinfo, tree, &pd);
652 tvb_2 = tvb_new_subset_remaining(tvb, (PWC_SIZEOF_CW-1));
653 if (MODE_11(pd.mode))
655 dissect_payload_and_padding(tvb_2, pinfo, tree, payload_size, 0, &pd);
657 else
658 { /*aal5_pdu mode*/
659 if (payload_size != 0)
661 tvbuff_t* tvb_3;
662 union wtap_pseudo_header* pseudo_header_save;
663 union wtap_pseudo_header ph;
665 tvb_3 = tvb_new_subset_remaining(tvb_2, 1);
666 /* prepare pseudo header for atm aal5 decoding */
667 pseudo_header_save = pinfo->pseudo_header;
668 pinfo->pseudo_header = &ph;
669 prepare_pseudo_header_atm(&ph, &pd, AAL_5);
670 call_dissector_with_data(dh_atm_untruncated, tvb_3, pinfo, tree, &pd);
671 /* restore pseudo header */
672 pinfo->pseudo_header = pseudo_header_save;
677 if (MODE_11(pd.mode))
679 /* overwrite everything written by sub-dissectors in 1:1 modes*/
680 col_set_str(pinfo->cinfo, COL_PROTOCOL, proto_name_column);
681 col_clear(pinfo->cinfo, COL_INFO);
682 col_append_pw_info(pinfo, payload_size, cells, 0, &pd);
685 return;
689 static void
690 dissect_aal5_sdu(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
692 const char * proto_name_column;
693 gint payload_size;
694 gint padding_size;
695 int cells;
696 pwatm_private_data_t pd = PWATM_PRIVATE_DATA_T_INITIALIZER;
698 pd.mode = PWATM_MODE_AAL5_SDU;
700 proto_name_column = &shortname_aal5_sdu[0];
701 if (too_small_packet_or_notpw(tvb, pinfo, tree, proto_aal5_sdu, proto_name_column))
703 return;
705 pd.packet_size = tvb_reported_length_remaining(tvb, 0);
707 /* check how "good" is this packet */
708 /* also decide payload length from packet size and CW */
709 if (0 != (tvb_get_guint8(tvb, 0) & 0xf0 /*bits03*/))
711 pd.props |= PWC_CW_BAD_BITS03;
714 pd.submode = PWATM_SUBMODE_DEFAULT;
715 if (0 != (tvb_get_guint8(tvb, 0) & 0x08 /*preferred_cw.T*/))
717 pd.submode = PWATM_SUBMODE_ADMIN_CELL;
720 if (! pref_aal5_sdu_extend_cw_length_with_rsvd)
722 if (0 != (tvb_get_guint8(tvb, 1) & 0xc0 /*preferred_cw.rsvd*/))
724 pd.props |= PWC_CW_BAD_RSV;
728 /* RFC4717:
729 * [ If the packet's length (defined as the length of the layer 2 payload
730 * plus the length of the control word) is less than 64 bytes, the
731 * length field MUST be set to the packet's length. Otherwise, the
732 * length field MUST be set to zero... Note that the length field
733 * is not used in the N-to-one mode and MUST be set to 0. ]
735 * Also we allow some "extensions"conducted by pref_xxx.
737 gint payload_size_from_packet;
738 int cw_len; /*length field from cw*/
740 payload_size_from_packet = pd.packet_size - PWC_SIZEOF_CW;
741 if (pref_aal5_sdu_extend_cw_length_with_rsvd)
743 cw_len = tvb_get_guint8(tvb, 1) & 0xff;
745 else
747 cw_len = tvb_get_guint8(tvb, 1) & 0x3f;
751 * Initial assumptions: no padding,
752 * payload size derived from psn packet size.
754 payload_size = payload_size_from_packet;
755 padding_size = 0;
757 if (0 == cw_len)
759 /*keep initial assumptions*/
761 else if (!pref_aal5_sdu_allow_cw_length_nonzero
762 && (PWATM_SUBMODE_ADMIN_CELL == pd.submode))
765 * The "allow CW.Length != 0" option affects
766 * ATM admin cell submode only, because this submode
767 * is equal to N:1 encapsulation.
768 * CW.Length !=0 is always OK for normal (AAL5 payload) submode.
770 pd.props |= PWC_CW_BAD_LEN_MUST_BE_0;
772 else
774 gint payload_size_from_cw;
775 payload_size_from_cw = cw_len - PWC_SIZEOF_CW;
776 if (payload_size_from_cw <= 0)
778 pd.props |= PWC_CW_BAD_PAYLEN_LE_0;
780 else if (payload_size_from_cw > payload_size_from_packet)
782 pd.props |= PWC_CW_BAD_PAYLEN_GT_PACKET;
784 else
787 payload_size = payload_size_from_cw;
788 padding_size = payload_size_from_packet - payload_size_from_cw; /* >=0 */
789 if (padding_size != 0)
792 * Padding is not allowed in ATM admin cell submode only,
793 * because this submode is equal to N:1 encapsulation.
794 * Padding is OK for normal (AAL5 payload) submode.
796 if (PWATM_SUBMODE_ADMIN_CELL == pd.submode)
798 pd.props |= PWC_CW_BAD_PADDING_NE_0;
799 /*restore sizes*/
800 payload_size = payload_size_from_packet;
801 padding_size = 0;
807 if (PWATM_SUBMODE_ADMIN_CELL == pd.submode)
809 gint bad_padding_size;
810 cells = number_of_cells(pd.mode, pd.submode, payload_size, &bad_padding_size);
811 /* only one atm admin cell is allowed in the packet in this mode*/
812 if ((1 != cells) || (0 != bad_padding_size))
814 pd.props |= PWC_PAY_SIZE_BAD;
817 else
819 cells = -1; /*unknown*/
820 /* Any size is allowed for AAL5 SDU payload */
824 /* fill columns in Packet List */
825 col_set_str(pinfo->cinfo, COL_PROTOCOL, proto_name_column);
826 if (PWATM_SUBMODE_ADMIN_CELL == pd.submode)
828 col_append_str(pinfo->cinfo, COL_PROTOCOL, ", OAM cell");
831 col_clear(pinfo->cinfo, COL_INFO);
832 col_append_pw_info(pinfo, payload_size, cells, padding_size, &pd);
835 proto_item* item;
836 item = proto_tree_add_item(tree, proto_aal5_sdu, tvb, 0, -1, ENC_NA);
838 proto_tree* tree2;
839 tree2 = proto_item_add_subtree(item, ett_encaps);
841 item = proto_tree_add_boolean(tree2, hf_pw_type_aal5_sdu, tvb, 0, 0, TRUE);
842 PROTO_ITEM_SET_GENERATED(item);
845 if (pd.props & PWC_PAY_SIZE_BAD)
847 DISSECTOR_ASSERT(PWATM_SUBMODE_ADMIN_CELL == pd.submode);
848 expert_add_info_format(pinfo, item, &ei_pw_payload_size_invalid_error,
849 "In ATM admin cell mode,"
850 " PW payload size (%d) must be == %d (exactly 1 admin cell)",
851 (int)payload_size, (int)SIZEOF_N1_PW_CELL);
856 tvbuff_t* tvb_2;
857 tvb_2 = tvb_new_subset(tvb, 0, PWC_SIZEOF_CW, PWC_SIZEOF_CW);
858 call_dissector_with_data(dh_control_word, tvb_2, pinfo, tree, &pd);
860 tvb_2 = tvb_new_subset_remaining(tvb, PWC_SIZEOF_CW);
861 if (PWATM_SUBMODE_ADMIN_CELL == pd.submode)
863 dissect_payload_and_padding(tvb_2, pinfo, tree, payload_size, padding_size, &pd);
865 else /*AAL5 payload*/
867 if (payload_size != 0)
869 tvbuff_t* tvb_3;
870 union wtap_pseudo_header* pseudo_header_save;
871 union wtap_pseudo_header ph;
873 tvb_3 = tvb_new_subset(tvb_2, 0, payload_size, payload_size);
874 /* prepare pseudo header for atm aal5 decoding */
875 pseudo_header_save = pinfo->pseudo_header;
876 pinfo->pseudo_header = &ph;
877 prepare_pseudo_header_atm(&ph, &pd, AAL_5);
878 call_dissector_with_data(dh_atm_truncated, tvb_3, pinfo, tree, &pd); /* no PAD and trailer */
879 /* restore pseudo header */
880 pinfo->pseudo_header = pseudo_header_save;
882 if (padding_size != 0)
884 tvbuff_t* tvb_3;
885 tvb_3 = tvb_new_subset(tvb_2, payload_size, padding_size, -1);
886 call_dissector(dh_padding, tvb_3, pinfo, tree);
893 static void
894 dissect_n1_cw(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
896 const char * proto_name_column;
897 gint payload_size;
898 gint padding_size;
899 int cells;
900 pwatm_private_data_t pd = PWATM_PRIVATE_DATA_T_INITIALIZER;
902 pd.mode = PWATM_MODE_N1_CW;
904 proto_name_column = &shortname_n1_cw[0];
905 if (too_small_packet_or_notpw(tvb, pinfo, tree, proto_n1_cw, proto_name_column))
907 return;
909 pd.packet_size = tvb_reported_length_remaining(tvb, 0);
911 /* check how "good" is this packet */
912 /* also decide payload length from packet size and CW */
913 pd.props = PWC_PACKET_PROPERTIES_T_INITIALIZER;
914 if (0 != (tvb_get_guint8(tvb, 0) & 0xf0 /*bits03*/))
916 pd.props |= PWC_CW_BAD_BITS03;
918 if (0 != (tvb_get_guint8(tvb, 0) & 0x0f /*preferred_cw.flags*/))
920 pd.props |= PWC_CW_BAD_FLAGS;
922 if (! pref_n1_cw_extend_cw_length_with_rsvd)
924 if (0 != (tvb_get_guint8(tvb, 1) & 0xc0 /*preferred_cw.rsvd*/))
926 pd.props |= PWC_CW_BAD_RSV;
930 /* RFC4717:
931 * [ If the packet's length (defined as the length of the layer 2 payload
932 * plus the length of the control word) is less than 64 bytes, the
933 * length field MUST be set to the packet's length. Otherwise, the
934 * length field MUST be set to zero... Note that the length field
935 * is not used in the N-to-one mode and MUST be set to 0. ]
937 * Also we allow some "extensions"conducted by pref_xxx.
939 gint payload_size_from_packet;
940 int cw_len; /*length field from cw*/
942 payload_size_from_packet = pd.packet_size - PWC_SIZEOF_CW;
943 if (pref_n1_cw_extend_cw_length_with_rsvd)
945 cw_len = tvb_get_guint8(tvb, 1) & 0xff;
947 else
949 cw_len = tvb_get_guint8(tvb, 1) & 0x3f;
953 * Initial assumptions: no padding,
954 * payload size derived from psn packet size.
956 payload_size = payload_size_from_packet;
957 padding_size = 0;
959 if (0 == cw_len)
961 /*keep initial assumptions*/
963 else if (!pref_n1_cw_allow_cw_length_nonzero)
965 pd.props |= PWC_CW_BAD_LEN_MUST_BE_0;
967 else
969 gint payload_size_from_cw;
970 payload_size_from_cw = cw_len - PWC_SIZEOF_CW;
971 if (payload_size_from_cw <= 0)
973 pd.props |= PWC_CW_BAD_PAYLEN_LE_0;
975 else if (payload_size_from_cw > payload_size_from_packet)
977 pd.props |= PWC_CW_BAD_PAYLEN_GT_PACKET;
979 else
982 payload_size = payload_size_from_cw;
983 padding_size = payload_size_from_packet - payload_size_from_cw; /* >=0 */
984 if (padding_size != 0)
986 pd.props |= PWC_CW_BAD_PADDING_NE_0;
987 /*restore sizes*/
988 payload_size = payload_size_from_packet;
989 padding_size = 0;
994 gint bad_padding_size;
995 cells = number_of_cells(pd.mode, pd.submode, payload_size, &bad_padding_size);
996 if ((0 == cells) || (0 != bad_padding_size))
998 pd.props |= PWC_PAY_SIZE_BAD;
1004 proto_item* item;
1005 item = proto_tree_add_item(tree, proto_n1_cw, tvb, 0, -1, ENC_NA);
1006 pwc_item_append_text_n_items(item, cells, "good ATM cell");
1008 proto_tree* tree2;
1009 tree2 = proto_item_add_subtree(item, ett_encaps);
1011 proto_item* item2;
1012 item2 = proto_tree_add_boolean(tree2, hf_pw_type_n1_cw, tvb, 0, 0, TRUE);
1013 PROTO_ITEM_SET_GENERATED(item2);
1014 item2 = proto_tree_add_int(tree2, hf_n1_cw_ncells, tvb, 0, 0, cells);
1015 PROTO_ITEM_SET_GENERATED(item2);
1018 if (pd.props & PWC_PAY_SIZE_BAD)
1020 if (payload_size != 0)
1022 expert_add_info_format(pinfo, item, &ei_cell_broken,
1023 "PW ATM cell [%.3d] is broken", (int)cells);
1024 expert_add_info_format(pinfo, item, &ei_pw_payload_size_invalid_note,
1025 "PW payload size (%d) must be <>0 and multiple of %d",
1026 (int)payload_size, (int)SIZEOF_N1_PW_CELL);
1028 else
1030 expert_add_info_format(pinfo, item, &ei_pw_payload_size_invalid_error,
1031 "PW payload size (%d) must be <>0 and multiple of %d",
1032 (int)payload_size, (int)SIZEOF_N1_PW_CELL);
1038 tvbuff_t* tvb_2;
1039 tvb_2 = tvb_new_subset(tvb, 0, PWC_SIZEOF_CW, PWC_SIZEOF_CW);
1040 call_dissector_with_data(dh_control_word, tvb_2, pinfo, tree, &pd);
1042 tvb_2 = tvb_new_subset_remaining(tvb, PWC_SIZEOF_CW);
1043 dissect_payload_and_padding(tvb_2, pinfo, tree, payload_size, padding_size, &pd);
1046 /* fill columns in Packet List */
1047 /* overwrite everything written by sub-dissectors */
1048 col_set_str(pinfo->cinfo, COL_PROTOCOL, proto_name_column);
1050 col_clear(pinfo->cinfo, COL_INFO);
1051 col_append_pw_info(pinfo, payload_size, cells, padding_size, &pd);
1055 static void
1056 dissect_n1_nocw(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
1058 const char * proto_name_column = &shortname_n1_nocw[0];
1059 gint payload_size;
1060 int cells;
1061 pwatm_private_data_t pd = PWATM_PRIVATE_DATA_T_INITIALIZER;
1063 pd.mode = PWATM_MODE_N1_NOCW;
1064 pd.packet_size = tvb_reported_length_remaining(tvb, 0);
1066 /* check how "good" is this packet */
1067 /* also decide payload length from packet size */
1068 pd.props = PWC_PACKET_PROPERTIES_T_INITIALIZER;
1069 payload_size = pd.packet_size;
1071 gint bad_padding_size;
1072 cells = number_of_cells(pd.mode, pd.submode, pd.packet_size, &bad_padding_size);
1073 if ((cells == 0) || (bad_padding_size != 0))
1075 pd.props |= PWC_PAY_SIZE_BAD;
1080 proto_item* item;
1081 item = proto_tree_add_item(tree, proto_n1_nocw, tvb, 0, -1, ENC_NA);
1082 pwc_item_append_text_n_items(item, cells, "ATM cell");
1084 proto_tree* tree2;
1085 tree2 = proto_item_add_subtree(item, ett_encaps);
1087 proto_item* item2;
1088 item2 = proto_tree_add_boolean(tree2, hf_pw_type_n1_nocw, tvb, 0, 0, TRUE);
1089 PROTO_ITEM_SET_GENERATED(item2);
1090 item2 = proto_tree_add_int(tree2, hf_n1_nocw_ncells, tvb, 0, 0, cells);
1091 PROTO_ITEM_SET_GENERATED(item2);
1094 if (pd.props & PWC_PAY_SIZE_BAD)
1096 if (payload_size != 0)
1098 expert_add_info_format(pinfo, item, &ei_cell_broken,
1099 "Last PW ATM cell [%.3d] is broken", (int)cells);
1100 expert_add_info_format(pinfo, item, &ei_pw_payload_size_invalid_note,
1101 "PW payload size (%d) must be <>0 and multiple of %d",
1102 (int)payload_size, (int)SIZEOF_N1_PW_CELL);
1104 else
1106 expert_add_info_format(pinfo, item, &ei_pw_payload_size_invalid_error,
1107 "PW payload size (%d) must be <>0 and multiple of %d",
1108 (int)payload_size, (int)SIZEOF_N1_PW_CELL);
1113 dissect_payload_and_padding(tvb, pinfo, tree, payload_size, 0, &pd);
1115 /* fill columns in Packet List */
1116 /* overwrite everything written by sub-dissectors */
1117 col_set_str(pinfo->cinfo, COL_PROTOCOL, proto_name_column);
1119 col_clear(pinfo->cinfo, COL_INFO);
1120 col_append_pw_info(pinfo, payload_size, cells, 0, &pd);
1124 static void
1125 proto_item_append_text_cwb3_fields(proto_item * item, const pwatm_private_data_t * const pd)
1127 if (NULL == item) return;
1128 DISSECTOR_ASSERT(NULL != pd);
1129 if (pd->cwb3.m >= 0)
1130 proto_item_append_text(item, "M:%.1u " , (unsigned)(pd->cwb3.m));
1131 if (pd->cwb3.v >= 0)
1132 proto_item_append_text(item, "V:%.1u " , (unsigned)(pd->cwb3.v));
1133 if (pd->cwb3.rsv >= 0)
1134 proto_item_append_text(item, "RSV:%.1u ", (unsigned)(pd->cwb3.rsv));
1135 if (pd->cwb3.u >= 0)
1136 proto_item_append_text(item, "U:%.1u " , (unsigned)(pd->cwb3.u));
1137 if (pd->cwb3.e >= 0)
1138 proto_item_append_text(item, "EFCI:%.1u ",(unsigned)(pd->cwb3.e));
1139 if (pd->cwb3.clp >= 0)
1140 proto_item_append_text(item, "CLP:%.1u ", (unsigned)(pd->cwb3.clp));
1141 return;
1145 static int
1146 dissect_control_word(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void* data)
1148 pwatm_private_data_t* pd = (pwatm_private_data_t *)data;
1149 DISSECTOR_ASSERT(pd != NULL);
1152 * NB: do not touch columns -- keep info from previous dissector
1156 gint size;
1157 size = tvb_reported_length_remaining(tvb, 0);
1158 if (size < PWC_SIZEOF_CW)
1160 proto_item *item;
1161 item = proto_tree_add_item(tree, proto_control_word, tvb, 0, -1, ENC_NA);
1162 expert_add_info_format(pinfo, item, &ei_pw_payload_size_invalid_error,
1163 "Packet (size: %d) is too small to carry MPLS PW Control Word"
1164 ,(int)size);
1165 return tvb_length(tvb);
1170 proto_item* item_top;
1171 proto_tree* tree2;
1172 proto_item* item;
1174 item_top = proto_tree_add_item(tree, proto_control_word, tvb, 0, -1, ENC_NA);
1175 pwc_item_append_cw(item_top, tvb_get_ntohl(tvb, 0), FALSE);
1177 tree2 = proto_item_add_subtree(item_top, ett_cw);
1179 /* bits 0..3 */
1180 item = proto_tree_add_item(tree2, hf_cw_bits03, tvb, 0, 1, ENC_BIG_ENDIAN);
1181 if (pd->props & PWC_CW_BAD_BITS03)
1183 /* add item to tree (and show it) only if its value is wrong*/
1184 expert_add_info(pinfo, item, &ei_cw_bits03);
1186 else
1188 PROTO_ITEM_SET_HIDDEN(item); /* show only in error cases */
1191 /* flags */
1192 if (MODE_N1(pd->mode))
1194 item = proto_tree_add_item(tree2, hf_pref_cw_flags, tvb, 0, 1, ENC_BIG_ENDIAN);
1195 if (pd->props & PWC_CW_BAD_FLAGS)
1197 expert_add_info(pinfo, item, &ei_pref_cw_flags);
1200 if (pd->mode == PWATM_MODE_AAL5_SDU)
1202 proto_tree_add_item(tree2, hf_pref_cw_a5s_t, tvb, 0, 1, ENC_BIG_ENDIAN);
1203 proto_tree_add_item(tree2, hf_pref_cw_a5s_e, tvb, 0, 1, ENC_BIG_ENDIAN);
1204 proto_tree_add_item(tree2, hf_pref_cw_a5s_c, tvb, 0, 1, ENC_BIG_ENDIAN);
1205 proto_tree_add_item(tree2, hf_pref_cw_a5s_u, tvb, 0, 1, ENC_BIG_ENDIAN);
1207 * rfc4717: [When FRF.8.1 Frame Relay/ATM PVC Service Interworking [RFC3916]
1208 * traffic is being transported, the CPCS-UU Least Significant Bit
1209 * (LSB) of the AAL5 CPCS-PDU may contain the Frame Relay C/R bit.
1210 * The ingress router, PE1, SHOULD copy this bit to the U bit of the
1211 * control word. The egress router, PE2, SHOULD copy the U bit to
1212 * the CPCS-UU Least Significant Bit (LSB) of the AAL5 CPCS PDU.]
1214 * Let's remember this bit (and then transfer it to ATM dissector).
1216 pd->aal5_sdu_frame_relay_cr_bit =
1217 (0 == (tvb_get_guint8(tvb, 0) & 0x01 /*preferred_cw.U*/))
1218 ? FALSE : TRUE;
1221 /* reserved bits */
1222 if (MODE_11_OR_AAL5_PDU(pd->mode)
1223 || (MODE_N1(pd->mode) && !pref_n1_cw_extend_cw_length_with_rsvd)
1224 /* for N:1 add RSV only if it is NOT used in length */
1225 || ((pd->mode == PWATM_MODE_AAL5_SDU) && !pref_aal5_sdu_extend_cw_length_with_rsvd)
1226 /* for AAl5 SDU add RSV only if it is NOT used in length */)
1228 if (MODE_11_OR_AAL5_PDU(pd->mode))
1230 item = proto_tree_add_item(tree2
1231 ,hf_generic_cw_rsv, tvb, 0, 1, ENC_BIG_ENDIAN);
1233 else
1234 { /*preferred cw*/
1235 item = proto_tree_add_item(tree2
1236 ,hf_pref_cw_rsv, tvb, 1, 1, ENC_BIG_ENDIAN);
1239 if (pd->props & PWC_CW_BAD_RSV)
1241 expert_add_info(pinfo, item, &ei_cw_bits03);
1243 else
1245 PROTO_ITEM_SET_HIDDEN(item); /*...and show only in error cases */
1249 /* length */
1250 if (MODE_N1(pd->mode)
1251 || (PWATM_MODE_AAL5_SDU == pd->mode))
1254 int hf_len = hf_pref_cw_len;
1255 if (MODE_N1(pd->mode))
1257 if (pref_n1_cw_extend_cw_length_with_rsvd)
1258 hf_len = hf_pref_cw_rsvlen;
1260 else /*PW_MODE_AAL5_SDU*/
1262 if (pref_aal5_sdu_extend_cw_length_with_rsvd)
1263 hf_len = hf_pref_cw_rsvlen;
1265 item = proto_tree_add_item(tree2, hf_len, tvb, 1, 1, ENC_BIG_ENDIAN);
1267 if (pd->props & PWC_CW_BAD_LEN_MUST_BE_0)
1269 expert_add_info_format(pinfo, item, &ei_pref_cw_len,
1270 "Bad Length: must be 0 for this encapsulation");
1272 if (pd->props & PWC_CW_BAD_PAYLEN_LE_0)
1274 expert_add_info_format(pinfo, item, &ei_pref_cw_len,
1275 "Bad Length: too small, must be >= %d",
1276 (int)(PWC_SIZEOF_CW+SIZEOF_N1_PW_CELL));
1278 if (pd->props & PWC_CW_BAD_PAYLEN_GT_PACKET)
1280 expert_add_info_format(pinfo, item, &ei_pref_cw_len,
1281 "Bad Length: must be <= than PSN packet size (%d)",
1282 (int)pd->packet_size);
1284 if (pd->props & PWC_CW_BAD_PADDING_NE_0)
1286 expert_add_info_format(pinfo, item, &ei_pref_cw_len,
1287 "Bad Length: must be == PSN packet size (%d), no padding allowed",
1288 (int)pd->packet_size);
1292 /* sequence number */
1293 proto_tree_add_item(tree2, hf_cw_seq, tvb
1294 ,MODE_11_OR_AAL5_PDU(pd->mode) ? 1 : 2, 2, ENC_BIG_ENDIAN);
1296 /* atm-specific byte */
1297 if (MODE_11(pd->mode))
1299 proto_tree_add_item(tree2, hf_gen_cw_atmbyte, tvb, 3, 1, ENC_BIG_ENDIAN);
1301 * no need to highlight item in the tree, therefore
1302 * expert_add_info_format() is not used here.
1304 item = proto_tree_add_text(tree2, tvb, 3, 1
1305 ,"ATM-specific byte of CW is fully dissected below as %s%s"
1306 ,(PWATM_MODE_11_VPC == pd->mode) ? "a part of " : ""
1307 ,"PW ATM Cell Header [000]");
1308 PROTO_ITEM_SET_GENERATED(item);
1310 * Note: if atm-specific byte contains something wrong
1311 * (e.g. non-zero RSV or inadequate V), CW is not
1312 * marked as "bad".
1316 /*3rd byte of CW*/
1317 if (PWATM_MODE_AAL5_PDU == pd->mode)
1319 tvbuff_t* tvb_2;
1320 tvb_2 = tvb_new_subset_remaining(tvb, (PWC_SIZEOF_CW-1));
1321 call_dissector_with_data(dh_cell_header, tvb_2, pinfo, tree2, pd);
1322 proto_item_append_text(item_top, ", ");
1323 proto_item_append_text_cwb3_fields(item_top, pd);
1327 return tvb_length(tvb);
1332 * This function is also used to dissect 3rd byte of CW in AAL5 PDU mode.
1334 static int
1335 dissect_cell_header(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void * data)
1337 pwatm_private_data_t * pd = (pwatm_private_data_t *)data;
1338 gboolean is_enough_data;
1339 int dissect_size;
1341 DISSECTOR_ASSERT (NULL != pd);
1342 pd->vpi = pd->vci = pd->pti = -1;
1343 pd->cwb3.clp = pd->cwb3.m = pd->cwb3.v = pd->cwb3.rsv = pd->cwb3.u = pd->cwb3.e = -1;
1345 if (PWATM_MODE_AAL5_PDU == pd->mode)
1347 if (tvb_reported_length_remaining(tvb, 0) < 1)
1349 is_enough_data = FALSE;
1350 dissect_size = 0;
1352 else
1354 is_enough_data = TRUE;
1355 dissect_size = 1;
1358 else
1360 gint size;
1361 size = tvb_reported_length_remaining(tvb, 0);
1363 if (size < pw_cell_header_size(pd->mode, pd->submode))
1365 is_enough_data = FALSE;
1366 dissect_size = size;
1368 else
1370 is_enough_data = TRUE;
1371 dissect_size = pw_cell_header_size(pd->mode, pd->submode);
1376 * NB: do not touch columns -- keep info from previous dissector
1379 /* Collect info for upper-level dissectors regardless of
1380 * the presence of the tree
1382 if (is_enough_data)
1384 guint8 tmp8;
1385 switch (pd->mode)
1387 case PWATM_MODE_AAL5_SDU:
1388 DISSECTOR_ASSERT(pd->submode == PWATM_SUBMODE_ADMIN_CELL);
1389 /*fallthrough for ATM admin cell submode only*/
1390 case PWATM_MODE_N1_CW:
1391 case PWATM_MODE_N1_NOCW:
1392 pd->vpi = (tvb_get_ntohs (tvb, 0) >> 4);
1393 pd->vci = (tvb_get_ntoh24(tvb, 1) >> 4) & 0xffff;
1394 tmp8 = (tvb_get_guint8(tvb, 3));
1395 pd->pti = (tmp8 >> 1) & 0x07;
1396 pd->cwb3.clp = (tmp8 >> 0) & 0x01;
1397 UPDATE_CUMULATIVE_VALUE(pd->cumulative.vpi, pd->vpi);
1398 UPDATE_CUMULATIVE_VALUE(pd->cumulative.vci, pd->vci);
1399 UPDATE_CUMULATIVE_VALUE(pd->cumulative.pti, pd->pti);
1400 UPDATE_CUMULATIVE_VALUE(pd->cumulative.clp, pd->cwb3.clp);
1402 * OAM cell mode is always used for aal5_sdu/admin_cell mode,
1403 * even if pti indicates user cell.
1405 pd->cell_mode_oam =
1406 ((pd->mode == PWATM_MODE_AAL5_SDU) && (pd->submode == PWATM_SUBMODE_ADMIN_CELL))
1407 || PTI_IS_ADMIN(pd->pti);
1408 break;
1409 case PWATM_MODE_11_VPC:
1410 pd->vci = tvb_get_ntohs(tvb, 1);
1411 UPDATE_CUMULATIVE_VALUE(pd->cumulative.vci, pd->vci);
1412 /*fallthrough*/
1413 case PWATM_MODE_11_VCC:
1414 tmp8 = (tvb_get_guint8(tvb, 0));
1415 pd->cwb3.m = (tmp8 >> 7) & 0x1;
1416 pd->cwb3.v = (tmp8 >> 6) & 0x1;
1417 pd->cwb3.rsv = (tmp8 >> 4) & 0x3;
1418 pd->pti = (tmp8 >> 1) & 0x7;
1419 pd->cwb3.clp = (tmp8 >> 0) & 0x1;
1420 UPDATE_CUMULATIVE_VALUE(pd->cumulative.pti, pd->pti);
1421 UPDATE_CUMULATIVE_VALUE(pd->cumulative.clp, pd->cwb3.clp);
1423 * OAM cell mode is possible if packet contains atm cell (m == 0).
1425 pd->cell_mode_oam = PTI_IS_ADMIN(pd->pti) && (pd->cwb3.m == 0);
1426 break;
1427 case PWATM_MODE_AAL5_PDU:
1428 tmp8 = (tvb_get_guint8(tvb, 0));
1429 pd->cwb3.m = (tmp8 >> 7) & 0x1;
1430 pd->cwb3.v = (tmp8 >> 6) & 0x1;
1431 pd->cwb3.rsv = (tmp8 >> 3) & 0x7;
1432 pd->cwb3.u = (tmp8 >> 2) & 0x1;
1433 pd->cwb3.e = (tmp8 >> 1) & 0x1;
1434 pd->cwb3.clp = (tmp8 >> 0) & 0x1;
1435 UPDATE_CUMULATIVE_VALUE(pd->cumulative.clp, pd->cwb3.clp);
1436 break;
1437 default:
1438 DISSECTOR_ASSERT_NOT_REACHED();
1439 break;
1444 proto_item* item;
1446 item = proto_tree_add_item(tree, proto_cell_header, tvb
1448 ,dissect_size
1449 ,ENC_NA);
1450 if (PWATM_MODE_AAL5_PDU == pd->mode)
1452 proto_item_set_text(item, "Third byte of Control Word"); /*overwrite heading line*/
1453 /* cwb3 fileds are appended to CW heading line, not here */
1455 else
1457 proto_item_append_text(item, " [%.3d]", pd->pw_cell_number);
1458 proto_item_append_text(item, ", ");
1459 if (pd->vpi >= 0)
1460 proto_item_append_text(item, "VPI:%.4u ", (unsigned)(pd->vpi));
1461 if (pd->vci >= 0)
1462 proto_item_append_text(item, "VCI:%.5u ", (unsigned)(pd->vci));
1463 if (pd->pti >= 0)
1464 proto_item_append_text(item, "PTI:%.1u ", (unsigned)(pd->pti));
1465 proto_item_append_text_cwb3_fields(item, pd);
1469 proto_tree* tree2;
1470 tree2 = proto_item_add_subtree(item, ett_cell_header);
1471 if (is_enough_data)
1473 proto_item* item2;
1474 if (MODE_N1(pd->mode)
1475 || ((pd->mode == PWATM_MODE_AAL5_SDU) && (pd->submode == PWATM_SUBMODE_ADMIN_CELL)))
1477 proto_tree_add_uint(tree2, hf_cell_h_vpi, tvb, 0, 2, (unsigned)pd->vpi);
1478 proto_tree_add_uint(tree2, hf_cell_h_vci, tvb, 1, 3, (unsigned)pd->vci);
1480 item2 = proto_tree_add_item(tree2, hf_cell_h_pti, tvb, 3, 1, ENC_BIG_ENDIAN);
1481 if (NULL == try_val_to_str(pd->pti, atm_pt_vals))
1483 expert_add_info_format(pinfo, item2, &ei_cell_h_pti_undecoded,
1484 "Unknown value of PTI field (%d) in the ATM cell header",
1485 pd->pti);
1487 else if ((pd->mode == PWATM_MODE_AAL5_SDU) && !PTI_IS_ADMIN(pd->pti))
1489 expert_add_info_format(pinfo, item2, &ei_cell_h_pti_malformed,
1490 "ATM admin cell is transerred;"
1491 " PTI field (%d) should be 4, 5 or 6.",
1492 pd->pti);
1495 proto_tree_add_item(tree2, hf_cell_h_clp, tvb, 3, 1, ENC_BIG_ENDIAN);
1497 else if (MODE_11_OR_AAL5_PDU(pd->mode))
1499 item2 = proto_tree_add_item(tree2, hf_cell_h_m , tvb, 0, 1, ENC_BIG_ENDIAN);
1500 if ((0 != pd->cwb3.m) && MODE_11(pd->mode))
1502 expert_add_info(pinfo, item2, &ei_cell_h_m);
1505 item2 = proto_tree_add_item(tree2, hf_cell_h_v , tvb, 0, 1, ENC_BIG_ENDIAN);
1506 if ((0 == pd->cwb3.v) && (PWATM_MODE_11_VPC == pd->mode))
1508 expert_add_info(pinfo, item2, &ei_cell_h_v_not_zero);
1510 if ((0 != pd->cwb3.v) && (PWATM_MODE_11_VCC == pd->mode))
1512 expert_add_info_format(pinfo, item2, &ei_cell_h_v_not_one,
1513 "1:1 VCC mode:"
1514 " V bit must be 0 to indicate that VCI is absent");
1516 if ((0 != pd->cwb3.v) && (PWATM_MODE_AAL5_PDU == pd->mode))
1518 expert_add_info_format(pinfo, item2, &ei_cell_h_v_not_one,
1519 "AAL5 PDU mode:"
1520 " V bit must be 0 to indicate that VCI is absent");
1523 item2 = proto_tree_add_item(tree2
1524 ,(PWATM_MODE_AAL5_PDU == pd->mode)
1525 ? hf_aal5_pdu_rsv
1526 : hf_cell_h_rsv
1527 ,tvb, 0, 1, ENC_BIG_ENDIAN);
1528 if (0 != pd->cwb3.rsv)
1530 expert_add_info(pinfo, item2, &ei_cell_h_rsv);
1532 else
1534 PROTO_ITEM_SET_HIDDEN(item2); /*...and show only in error cases */
1537 if (MODE_11(pd->mode))
1539 item2 = proto_tree_add_item(tree2, hf_cell_h_pti, tvb, 0, 1, ENC_BIG_ENDIAN);
1540 if (NULL == try_val_to_str(pd->pti, atm_pt_vals))
1542 expert_add_info_format(pinfo, item2, &ei_cell_h_pti_undecoded,
1543 "Unknown value of PTI field (%d) in the atm-specific byte"
1544 ,pd->pti);
1547 else
1549 proto_tree_add_item(tree2, hf_aal5_pdu_u, tvb, 0, 1, ENC_BIG_ENDIAN);
1550 proto_tree_add_item(tree2, hf_aal5_pdu_e, tvb, 0, 1, ENC_BIG_ENDIAN);
1553 proto_tree_add_item(tree2, hf_cell_h_clp, tvb, 0, 1, ENC_BIG_ENDIAN);
1555 if (PWATM_MODE_11_VPC == pd->mode)
1557 proto_tree_add_uint(tree2, hf_cell_h_vci, tvb, 1, 2
1558 ,(unsigned)pd->vci);
1561 else
1563 DISSECTOR_ASSERT_NOT_REACHED();
1566 else
1568 expert_add_info_format(pinfo, item, &ei_pw_payload_size_invalid_error,
1569 "Not enough data (size: %d), impossible to decode",
1570 (int)dissect_size);
1574 return dissect_size;
1579 static int
1580 dissect_cell(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void * data)
1582 gboolean is_enough_data;
1583 int dissect_size;
1584 gint size;
1585 proto_item* item;
1586 pwatm_private_data_t * pd = (pwatm_private_data_t *)data;
1588 size = tvb_reported_length_remaining(tvb, 0);
1589 if (size < SIZEOF_ATM_CELL_PAYLOAD)
1591 is_enough_data = FALSE;
1592 dissect_size = size;
1594 else
1596 is_enough_data = TRUE;
1597 dissect_size = SIZEOF_ATM_CELL_PAYLOAD;
1601 * NB: do not touch columns -- keep info from previous dissector
1604 item = proto_tree_add_item(tree, proto_cell, tvb, 0, dissect_size, ENC_NA);
1605 if (NULL != pd)
1606 proto_item_append_text(item, " [%.3d]", pd->pw_cell_number);
1608 pwc_item_append_text_n_items(item, dissect_size, "byte");
1609 if (!is_enough_data)
1611 expert_add_info_format(pinfo, item, &ei_pw_payload_size_invalid_error,
1612 "Bad length of cell payload: must be == %d",
1613 (int)SIZEOF_ATM_CELL_PAYLOAD);
1617 proto_tree* tree2;
1618 tvbuff_t* tvb_d;
1619 tree2 = proto_item_add_subtree(item, ett_cell);
1620 tvb_d = tvb_new_subset(tvb, 0, dissect_size, -1);
1621 call_dissector(dh_data, tvb_d, pinfo, tree2);
1622 item = proto_tree_add_int(tree2, hf_cell_payload_len, tvb, 0, 0, dissect_size);
1623 PROTO_ITEM_SET_HIDDEN(item);
1626 return dissect_size;
1630 void
1631 proto_register_pw_atm_ata(void)
1633 static const value_string clp_vals[] = {
1634 { 0, "High priority" },
1635 { 1, "Low priority" },
1636 { 0, NULL }
1638 static const value_string m_vals[] = {
1639 { 0, "ATM cell" },
1640 { 1, "AAL5 payload" },
1641 { 0, NULL }
1643 static const value_string u_vals[] = {
1644 { 0, "This frame does not contain the last cell of AAL5 PDU" },
1645 { 1, "This frame contains the last cell of AAL5 PDU" },
1646 { 0, NULL }
1648 static const value_string e_vals[] = {
1649 { 0, "Congestion is not experienced" },
1650 { 1, "Congestion is experienced for one or more ATM AAL5 cells" },
1651 { 0, NULL }
1653 static hf_register_info hfa_cell_header[] = {
1654 { &hf_cell_h_vpi ,{"VPI" ,"atm.vpi"
1655 ,FT_UINT16 ,BASE_DEC ,NULL ,0
1656 ,NULL ,HFILL }},
1658 { &hf_cell_h_vci ,{"VCI" ,"atm.vci"
1659 ,FT_UINT16 ,BASE_DEC ,NULL ,0
1660 ,NULL ,HFILL }},
1662 { &hf_cell_h_pti ,{"Payload Type" ,"atm.pti"
1663 ,FT_UINT8 ,BASE_DEC ,VALS(atm_pt_vals),0x0e
1664 ,"The 3-bit Payload Type Identifier (PTI) incorporates ATM Layer"
1665 " PTI coding of the cell. These bits are set to the value of the"
1666 " PTI of the encapsulated ATM cell."
1667 ,HFILL }},
1669 { &hf_cell_h_clp ,{"Cell Loss Priority" ,"atm.clp"
1670 ,FT_UINT8 ,BASE_DEC ,VALS(clp_vals) ,0x01
1671 ,"The Cell Loss Priority (CLP) field indicates CLP value"
1672 " of the encapsulated cell."
1673 ,HFILL }},
1675 { &hf_cell_h_m ,{"Transport Mode" ,"atm.pw_control_byte.m"
1676 ,FT_UINT8 ,BASE_DEC ,VALS(m_vals) ,0x80
1677 ,"Bit (M) of the control byte indicates whether the packet"
1678 " contains an ATM cell or a frame payload. If set to 0,"
1679 " the packet contains an ATM cell. If set to 1, the PDU"
1680 " contains an AAL5 payload."
1681 ,HFILL }},
1683 { &hf_cell_h_v ,{"VCI Present" ,"atm.pw_control_byte.v"
1684 ,FT_BOOLEAN ,8 ,TFS(&tfs_yes_no),0x40
1685 ,"Bit (V) of the control byte indicates whether the VCI field"
1686 " is present in the packet. If set to 1, the VCI field is present"
1687 " for the cell. If set to 0, no VCI field is present."
1688 ,HFILL }},
1690 { &hf_cell_h_rsv ,{"Reserved bits" ,"atm.pw_control_byte.rsv"
1691 ,FT_UINT8 ,BASE_DEC ,NULL ,0x30
1692 ,"The reserved bits should be set to 0 at the transmitter and"
1693 " ignored upon reception."
1694 ,HFILL }},
1696 { &hf_aal5_pdu_rsv ,{"Reserved bits" ,"atm.pw_control_byte.rsv"
1697 ,FT_UINT8 ,BASE_DEC ,NULL ,0x38
1698 ,"The reserved bits should be set to 0 at the transmitter and"
1699 " ignored upon reception."
1700 ,HFILL }},
1702 { &hf_aal5_pdu_u ,{"U bit" ,"atm.pw_control_byte.u"
1703 ,FT_UINT8 ,BASE_DEC ,VALS(u_vals) ,0x04
1704 ,"Indicates whether this frame contains the last cell of"
1705 " an AAL5 PDU and represents the value of the ATM User-to-User"
1706 " bit for the last ATM cell of the PSN frame. Note: The ATM"
1707 " User-to-User bit is the least significant bit of the PTI"
1708 " in the ATM header."
1709 ,HFILL }},
1711 { &hf_aal5_pdu_e ,{"EFCI" ,"atm.pw_control_byte.efci"
1712 ,FT_UINT8 ,BASE_DEC ,VALS(e_vals) ,0x02
1713 ,"EFCI is set to the EFCI state of the last cell of the"
1714 " AAL5 PDU or AAL5 fragment. Note: The EFCI state is"
1715 " indicated in the middle bit of each ATM cell's PTI."
1716 ,HFILL }}
1718 static hf_register_info hfa_cell[] = {
1719 {&hf_cell_payload_len ,{"Length" ,"atm.cell.len"
1720 ,FT_INT32 ,BASE_DEC ,NULL ,0
1721 ,NULL ,HFILL }}
1724 #define HF_INITIALIZER_NCELLS(hf_handle) \
1725 { &hf_handle ,{"Number of good encapsulated cells","pw.atm.cells" \
1726 ,FT_INT32 ,BASE_DEC ,NULL ,0 \
1727 ,NULL ,HFILL }}
1729 #define HF_INITIALIZER_PWTYPE(hf_handle,name) \
1730 { &hf_handle ,{name ,name \
1731 ,FT_BOOLEAN ,0 ,NULL ,0x0 \
1732 ,"Identifies type of ATM PW. May be used for filtering.",HFILL}}
1735 static hf_register_info hfa_n1_nocw[] = {
1736 HF_INITIALIZER_NCELLS(hf_n1_nocw_ncells)
1737 ,HF_INITIALIZER_PWTYPE(hf_pw_type_n1_nocw,"pw.type.atm.n1nocw")
1740 static hf_register_info hfa_n1_cw[] = {
1741 HF_INITIALIZER_NCELLS(hf_n1_cw_ncells)
1742 ,HF_INITIALIZER_PWTYPE(hf_pw_type_n1_cw,"pw.type.atm.n1cw")
1745 static hf_register_info hfa_11_aal5pdu[] = {
1746 HF_INITIALIZER_NCELLS(hf_11_ncells)
1747 ,HF_INITIALIZER_PWTYPE(hf_pw_type_11_vcc,"pw.type.atm.11vcc")
1748 ,HF_INITIALIZER_PWTYPE(hf_pw_type_11_vpc,"pw.type.atm.11vpc")
1749 ,HF_INITIALIZER_PWTYPE(hf_pw_type_aal5_pdu,"pw.type.atm.aal5pdu")
1752 static hf_register_info hfa_aal5_sdu[] = {
1753 HF_INITIALIZER_PWTYPE(hf_pw_type_aal5_sdu,"pw.type.atm.aal5sdu")
1756 static const value_string a5s_t_vals[] = {
1757 { 0, "AAL5 payload" },
1758 { 1, "ATM admin cell" },
1759 { 0, NULL }
1762 static const value_string a5s_e_vals[] = {
1763 { 0, "No congestion" },
1764 { 1, "Congestion experienced" },
1765 { 0, NULL }
1768 static hf_register_info hfa_cw[] = {
1769 { &hf_cw_bits03 ,{"Bits 0 to 3" ,"pw.cw.bits03"
1770 ,FT_UINT8 ,BASE_HEX ,NULL ,0xf0
1771 ,NULL ,HFILL }},
1773 { &hf_pref_cw_flags ,{"Flags" ,"pw.cw.flags"
1774 ,FT_UINT8 ,BASE_HEX ,NULL ,0x0f
1775 ,NULL ,HFILL }},
1777 { &hf_pref_cw_a5s_t ,{"Payload type" ,"atm.pt"
1778 ,FT_UINT8 ,BASE_DEC ,VALS(a5s_t_vals),0x08
1779 ,"Bit (T) of the control word indicates whether the packet contains"
1780 " an ATM admin cell or an AAL5 payload. If T = 1, the packet"
1781 " contains an ATM admin cell, encapsulated according to the N:1"
1782 " cell relay encapsulation. If not set, the PDU"
1783 " contains an AAL5 payload."
1784 ,HFILL }},
1786 { &hf_pref_cw_a5s_e ,{"EFCI bit" ,"atm.efci"
1787 ,FT_UINT8 ,BASE_DEC ,VALS(a5s_e_vals),0x04
1788 ,"The ingress router sets this bit to 1 if the EFCI bit"
1789 " of the final cell of those that transported the AAL5 CPCS-SDU is"
1790 " set to 1, or if the EFCI bit of the single ATM cell to be"
1791 " transported in the packet is set to 1. Otherwise, this bit"
1792 " is set to 0."
1793 ,HFILL }},
1795 { &hf_pref_cw_a5s_c ,{"CLP bit" ,"atm.clp"
1796 ,FT_UINT8 ,BASE_DEC ,VALS(clp_vals) ,0x02
1797 ,"The ingress router sets this bit to 1 if the CLP bit"
1798 " of any of the ATM cells that transported the AAL5 CPCS-SDU is set"
1799 " to 1, or if the CLP bit of the single ATM cell to be transported"
1800 " in the packet is set to 1. Otherwise this bit is set to 0."
1801 ,HFILL }},
1803 { &hf_pref_cw_a5s_u ,{"U bit (Command/Response)" ,"pw.cw.aal5sdu.u"
1804 ,FT_UINT8 ,BASE_DEC ,NULL ,0x01
1805 ,"When FRF.8.1 Frame Relay/ATM PVC Service Interworking [RFC3916]"
1806 " traffic is being transported, the Least-Significant Bit of CPCS-UU"
1807 " of the AAL5 CPCS-PDU may contain the Frame Relay C/R bit."
1808 " The ingress router copies this bit here."
1809 ,HFILL }},
1811 { &hf_pref_cw_rsv ,{"Reserved bits" ,"pw.cw.rsv"
1812 ,FT_UINT8 ,BASE_DEC ,NULL ,0xc0
1813 ,NULL ,HFILL }},
1815 { &hf_generic_cw_rsv ,{"Reserved bits" ,"pw.cw.rsv"
1816 ,FT_UINT8 ,BASE_DEC ,NULL ,0x0f
1817 ,NULL ,HFILL }},
1819 { &hf_pref_cw_len ,{"Length" ,"pw.cw.length"
1820 ,FT_UINT8 ,BASE_DEC ,NULL ,0x3f
1821 ,NULL ,HFILL }},
1823 { &hf_pref_cw_rsvlen ,{"Length (extended)" ,"pw.cw.length"
1824 ,FT_UINT8 ,BASE_DEC ,NULL ,0xff
1825 ,NULL ,HFILL }},
1827 { &hf_cw_seq ,{"Sequence number" ,"pw.cw.seqno"
1828 ,FT_UINT16 ,BASE_DEC ,NULL ,0
1829 ,NULL ,HFILL }},
1831 { &hf_gen_cw_atmbyte ,{"ATM-specific byte" ,"pw.cw.3rd_byte"
1832 ,FT_UINT8 ,BASE_HEX ,NULL ,0xFF
1833 ,NULL ,HFILL }}
1835 static gint *ett_array[] = {
1836 &ett_encaps
1837 ,&ett_cw
1838 ,&ett_cell_header
1839 ,&ett_cell
1841 static ei_register_info ei[] = {
1842 { &ei_pw_packet_size_too_small, { "pw.packet_size_too_small", PI_MALFORMED, PI_ERROR, "PW packet size too small", EXPFILL }},
1843 { &ei_pw_payload_size_invalid_error, { "pw.payload.size_invalid", PI_MALFORMED, PI_ERROR, "PW payload size invalid", EXPFILL }},
1844 { &ei_cell_broken, { "atm.cell_broken", PI_MALFORMED, PI_ERROR, "PW ATM cell is broken", EXPFILL }},
1845 { &ei_pw_payload_size_invalid_note, { "pw.payload.size_invalid", PI_MALFORMED, PI_NOTE, "PW payload size invalid", EXPFILL }},
1846 { &ei_cw_bits03, { "pw.cw.bits03.not_zero", PI_MALFORMED, PI_ERROR, "Bits 0..3 of Control Word must be 0", EXPFILL }},
1847 { &ei_pref_cw_flags, { "pw.cw.flags.not_zero", PI_MALFORMED, PI_ERROR, "Flags must be 0 for PW ATM N:1 encapsulation", EXPFILL }},
1848 { &ei_pref_cw_len, { "pw.cw.length.invalid", PI_MALFORMED, PI_ERROR, "Bad Length: must be 0 for this encapsulation", EXPFILL }},
1849 { &ei_cell_h_pti_undecoded, { "atm.pti.invalid", PI_UNDECODED, PI_WARN, "Unknown value of PTI field in the ATM cell header", EXPFILL }},
1850 { &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 }},
1851 { &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 }},
1852 { &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 }},
1853 { &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 }},
1854 { &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 }},
1856 expert_module_t* expert_cell;
1858 proto_n1_cw =
1859 proto_register_protocol(pwc_longname_pw_atm_n1_cw
1860 ,shortname_n1_cw
1861 ,"mplspwatmn1cw");
1862 proto_11_or_aal5_pdu =
1863 proto_register_protocol(pwc_longname_pw_atm_11_or_aal5_pdu
1864 ,shortname_11_or_aal5_pdu
1865 ,"mplspwatm11_or_aal5pdu");
1866 proto_aal5_sdu =
1867 proto_register_protocol(pwc_longname_pw_atm_aal5_sdu
1868 ,shortname_aal5_sdu
1869 ,"mplspwatmaal5sdu");
1870 proto_n1_nocw =
1871 proto_register_protocol(pwc_longname_pw_atm_n1_nocw
1872 ,shortname_n1_nocw
1873 ,"mplspwatmn1nocw");
1874 proto_control_word =
1875 proto_register_protocol("MPLS PW ATM Control Word"
1876 ,"MPLS PW ATM Control Word"
1877 ,"mplspwatmcontrolword");
1878 proto_cell_header =
1879 proto_register_protocol("MPLS PW ATM Cell Header"
1880 ,"MPLS PW ATM Cell Header"
1881 ,"mplspwatmcellheader");
1882 proto_cell =
1883 proto_register_protocol("ATM Cell"
1884 ,"ATM Cell"
1885 ,"mplspwatmcell");
1887 proto_register_field_array( proto_cell ,hfa_cell ,array_length(hfa_cell));
1888 expert_cell = expert_register_protocol(proto_cell);
1889 expert_register_field_array(expert_cell, ei, array_length(ei));
1891 proto_register_field_array( proto_cell_header ,hfa_cell_header,array_length(hfa_cell_header));
1892 proto_register_field_array( proto_control_word ,hfa_cw ,array_length(hfa_cw));
1893 proto_register_field_array( proto_n1_nocw ,hfa_n1_nocw ,array_length(hfa_n1_nocw));
1894 proto_register_field_array( proto_n1_cw ,hfa_n1_cw ,array_length(hfa_n1_cw));
1895 proto_register_field_array( proto_11_or_aal5_pdu ,hfa_11_aal5pdu ,array_length(hfa_11_aal5pdu));
1896 proto_register_field_array( proto_aal5_sdu ,hfa_aal5_sdu ,array_length(hfa_aal5_sdu));
1898 proto_register_subtree_array(ett_array, array_length(ett_array));
1900 register_dissector("mpls_pw_atm_aal5_sdu" ,dissect_aal5_sdu ,proto_aal5_sdu);
1901 register_dissector("mpls_pw_atm_11_or_aal5_pdu" ,dissect_11_or_aal5_pdu ,proto_11_or_aal5_pdu);
1902 register_dissector("mpls_pw_atm_n1_cw" ,dissect_n1_cw ,proto_n1_cw);
1903 register_dissector("mpls_pw_atm_n1_nocw" ,dissect_n1_nocw ,proto_n1_nocw);
1904 new_register_dissector("mpls_pw_atm_control_word" ,dissect_control_word ,proto_control_word);
1905 new_register_dissector("mpls_pw_atm_cell" ,dissect_cell ,proto_cell);
1906 new_register_dissector("mpls_pw_atm_cell_header",dissect_cell_header ,proto_cell_header);
1908 static const char description_allow_cw_length_nonzero[] =
1909 "Enable to allow non-zero Length in Control Word."
1910 " This may be needed to correctly decode traffic from some legacy devices"
1911 " which generate non-zero Length even if there is no padding in the packet."
1912 " Note that Length should have proper value (dissector checks this anyway)."
1913 "\n\n"
1914 "Disable to blame all packets with CW.Length <> 0. This conforms to RFC4717."
1916 static const char description_extend_cw_length_with_rsvd[] =
1917 "Enable to use reserved bits (8..9) of Control Word as an extension of CW.Length."
1918 " This may be needed to correctly decode traffic from some legacy devices"
1919 " which uses reserved bits as extension of Length"
1920 "\n\n"
1921 "Disable to blame all packets with CW.Reserved <> 0. This conforms to RFC4717."
1923 module_t * module_n1_cw;
1924 module_t * module_aal5_sdu;
1926 module_n1_cw = prefs_register_protocol(proto_n1_cw,NULL);
1927 prefs_register_bool_preference(module_n1_cw
1928 ,"allow_cw_length_nonzero"
1929 ,"Allow CW.Length <> 0"
1930 ,&description_allow_cw_length_nonzero[0]
1931 ,&pref_n1_cw_allow_cw_length_nonzero);
1932 prefs_register_bool_preference(module_n1_cw
1933 ,"extend_cw_length_with_rsvd"
1934 ,"Use CW.Reserved as extension of CW.Length"
1935 ,&description_extend_cw_length_with_rsvd[0]
1936 ,&pref_n1_cw_extend_cw_length_with_rsvd);
1938 module_aal5_sdu = prefs_register_protocol(proto_aal5_sdu,NULL);
1939 prefs_register_bool_preference(module_aal5_sdu
1940 ,"allow_cw_length_nonzero_aal5"
1941 ,"Allow CW.Length <> 0"
1942 ,&description_allow_cw_length_nonzero[0]
1943 ,&pref_aal5_sdu_allow_cw_length_nonzero);
1944 prefs_register_bool_preference(module_aal5_sdu
1945 ,"extend_cw_length_with_rsvd_aal5"
1946 ,"Use CW.Reserved as extension of CW.Length"
1947 ,&description_extend_cw_length_with_rsvd[0]
1948 ,&pref_aal5_sdu_extend_cw_length_with_rsvd);
1953 void
1954 proto_reg_handoff_pw_atm_ata(void)
1956 dissector_handle_t h;
1957 h = find_dissector("mpls_pw_atm_n1_cw");
1958 dissector_add_uint( "mpls.label", MPLS_LABEL_INVALID, h );
1959 h = find_dissector("mpls_pw_atm_n1_nocw");
1960 dissector_add_uint( "mpls.label", MPLS_LABEL_INVALID, h );
1961 h = find_dissector("mpls_pw_atm_11_or_aal5_pdu");
1962 dissector_add_uint( "mpls.label", MPLS_LABEL_INVALID, h );
1963 h = find_dissector("mpls_pw_atm_aal5_sdu");
1964 dissector_add_uint( "mpls.label", MPLS_LABEL_INVALID, h );
1966 dh_cell = find_dissector("mpls_pw_atm_cell");
1967 dh_cell_header = find_dissector("mpls_pw_atm_cell_header");
1968 dh_control_word = find_dissector("mpls_pw_atm_control_word");
1969 dh_atm_truncated = find_dissector("atm_truncated");
1970 dh_atm_untruncated = find_dissector("atm_untruncated");
1971 dh_atm_oam_cell = find_dissector("atm_oam_cell");
1972 dh_padding = find_dissector("pw_padding");
1973 dh_data = find_dissector("data");