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