Coverage Report

Created: 2026-09-28 06:52

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