checkAPIs.pl: support for new-style dissectors in check_hf_entries
[metze/wireshark/wip.git] / epan / dissectors / packet-atm.c
1 /* packet-atm.c
2  * Routines for ATM packet disassembly
3  *
4  * Wireshark - Network traffic analyzer
5  * By Gerald Combs <gerald@wireshark.org>
6  * Copyright 1998 Gerald Combs
7  *
8  * SPDX-License-Identifier: GPL-2.0-or-later
9  */
10
11 #include "config.h"
12
13 #include <epan/packet.h>
14 #include <epan/capture_dissectors.h>
15 #include <wsutil/pint.h>
16 #include <epan/oui.h>
17 #include <epan/addr_resolv.h>
18 #include <epan/ppptypes.h>
19 #include <epan/expert.h>
20 #include <epan/crc10-tvb.h>
21 #include <epan/crc32-tvb.h>
22 #include <epan/decode_as.h>
23
24 #include "packet-atm.h"
25 #include "packet-snmp.h"
26 #include "packet-eth.h"
27 #include "packet-tr.h"
28 #include "packet-llc.h"
29 #include <epan/prefs.h>
30 #include "packet-pw-atm.h"
31
32 void proto_register_atm(void);
33 void proto_reg_handoff_atm(void);
34
35 static int proto_atm = -1;
36 static int hf_atm_aal = -1;
37 static int hf_atm_gfc = -1;
38 static int hf_atm_vpi = -1;
39 static int hf_atm_vci = -1;
40 static int hf_atm_cid = -1;
41 static int hf_atm_reserved = -1;
42 static int proto_atm_lane = -1;
43 static int proto_ilmi = -1;
44 static int proto_aal1 = -1;
45 static int proto_aal3_4 = -1;
46 static int proto_oamaal = -1;
47
48 static int hf_atm_le_client_client = -1;
49 static int hf_atm_lan_destination_tag = -1;
50 static int hf_atm_lan_destination_mac = -1;
51 static int hf_atm_le_control_tlv_type = -1;
52 static int hf_atm_le_control_tlv_length = -1;
53 static int hf_atm_lan_destination_route_desc = -1;
54 static int hf_atm_lan_destination_lan_id = -1;
55 static int hf_atm_lan_destination_bridge_num = -1;
56 static int hf_atm_source_atm = -1;
57 static int hf_atm_target_atm = -1;
58 static int hf_atm_le_configure_join_frame_lan_type = -1;
59 static int hf_atm_le_configure_join_frame_max_frame_size = -1;
60 static int hf_atm_le_configure_join_frame_num_tlvs = -1;
61 static int hf_atm_le_configure_join_frame_elan_name_size = -1;
62 static int hf_atm_le_configure_join_frame_elan_name = -1;
63 static int hf_atm_le_registration_frame_num_tlvs = -1;
64 static int hf_atm_le_arp_frame_num_tlvs = -1;
65 static int hf_atm_le_verify_frame_num_tlvs = -1;
66 static int hf_atm_le_control_marker = -1;
67 static int hf_atm_le_control_protocol = -1;
68 static int hf_atm_le_control_version = -1;
69 static int hf_atm_le_control_opcode = -1;
70 static int hf_atm_le_control_status = -1;
71 static int hf_atm_le_control_transaction_id = -1;
72 static int hf_atm_le_control_requester_lecid = -1;
73 static int hf_atm_le_control_flags = -1;
74 static int hf_atm_le_control_flag_v2_capable = -1;
75 static int hf_atm_le_control_flag_selective_multicast = -1;
76 static int hf_atm_le_control_flag_v2_required = -1;
77 static int hf_atm_le_control_flag_proxy = -1;
78 static int hf_atm_le_control_flag_exclude_explorer_frames = -1;
79 static int hf_atm_le_control_flag_address = -1;
80 static int hf_atm_le_control_topology_change = -1;
81 static int hf_atm_traffic_type = -1;
82 static int hf_atm_traffic_vcmx = -1;
83 static int hf_atm_traffic_lane = -1;
84 static int hf_atm_traffic_ipsilon = -1;
85 static int hf_atm_cells = -1;
86 static int hf_atm_aal5_uu = -1;
87 static int hf_atm_aal5_cpi = -1;
88 static int hf_atm_aal5_len = -1;
89 static int hf_atm_aal5_crc = -1;
90 static int hf_atm_payload_type = -1;
91 static int hf_atm_cell_loss_priority = -1;
92 static int hf_atm_header_error_check = -1;
93 static int hf_atm_channel = -1;
94 static int hf_atm_aa1_csi = -1;
95 static int hf_atm_aa1_seq_count = -1;
96 static int hf_atm_aa1_crc = -1;
97 static int hf_atm_aa1_parity = -1;
98 static int hf_atm_aa1_payload = -1;
99 static int hf_atm_aal3_4_seg_type = -1;
100 static int hf_atm_aal3_4_seq_num = -1;
101 static int hf_atm_aal3_4_multiplex_id = -1;
102 static int hf_atm_aal3_4_information = -1;
103 static int hf_atm_aal3_4_length_indicator = -1;
104 static int hf_atm_aal3_4_crc = -1;
105 static int hf_atm_aal_oamcell_type = -1;
106 static int hf_atm_aal_oamcell_type_fm = -1;
107 static int hf_atm_aal_oamcell_type_pm = -1;
108 static int hf_atm_aal_oamcell_type_ad = -1;
109 static int hf_atm_aal_oamcell_type_ft = -1;
110 static int hf_atm_aal_oamcell_func_spec = -1;
111 static int hf_atm_aal_oamcell_crc = -1;
112 static int hf_atm_padding = -1;
113
114 static gint ett_atm = -1;
115 static gint ett_atm_lane = -1;
116 static gint ett_atm_lane_lc_lan_dest = -1;
117 static gint ett_atm_lane_lc_lan_dest_rd = -1;
118 static gint ett_atm_lane_lc_flags = -1;
119 static gint ett_atm_lane_lc_tlv = -1;
120 static gint ett_ilmi = -1;
121 static gint ett_aal1 = -1;
122 static gint ett_aal3_4 = -1;
123 static gint ett_oamaal = -1;
124
125 static expert_field ei_atm_reassembly_failed = EI_INIT;
126
127 static dissector_handle_t atm_handle;
128 static dissector_handle_t atm_untruncated_handle;
129
130 static dissector_handle_t eth_withoutfcs_handle;
131 static dissector_handle_t tr_handle;
132 static dissector_handle_t fr_handle;
133 static dissector_handle_t llc_handle;
134 static dissector_handle_t sscop_handle;
135 static dissector_handle_t ppp_handle;
136 static dissector_handle_t eth_maybefcs_handle;
137 static dissector_handle_t ip_handle;
138
139 static gboolean dissect_lanesscop = FALSE;
140
141 static dissector_table_t atm_type_aal2_table;
142 static dissector_table_t atm_type_aal5_table;
143
144 /*
145  * See
146  *
147  *      http://www.atmforum.org/atmforum/specs/approved.html
148  *
149  * for a number of ATM Forum specifications, e.g. the LAN Emulation
150  * over ATM 1.0 spec, whence I got most of this.
151  */
152
153 /* LE Control opcodes */
154 #define LE_CONFIGURE_REQUEST    0x0001
155 #define LE_CONFIGURE_RESPONSE   0x0101
156 #define LE_JOIN_REQUEST         0x0002
157 #define LE_JOIN_RESPONSE        0x0102
158 #define READY_QUERY             0x0003
159 #define READY_IND               0x0103
160 #define LE_REGISTER_REQUEST     0x0004
161 #define LE_REGISTER_RESPONSE    0x0104
162 #define LE_UNREGISTER_REQUEST   0x0005
163 #define LE_UNREGISTER_RESPONSE  0x0105
164 #define LE_ARP_REQUEST          0x0006
165 #define LE_ARP_RESPONSE         0x0106
166 #define LE_FLUSH_REQUEST        0x0007
167 #define LE_FLUSH_RESPONSE       0x0107
168 #define LE_NARP_REQUEST         0x0008
169 #define LE_TOPOLOGY_REQUEST     0x0009
170 #define LE_VERIFY_REQUEST       0x000A
171 #define LE_VERIFY_RESPONSE      0x010A
172
173 static const value_string le_control_opcode_vals[] = {
174   { LE_CONFIGURE_REQUEST,   "LE_CONFIGURE_REQUEST" },
175   { LE_CONFIGURE_RESPONSE,  "LE_CONFIGURE_RESPONSE" },
176   { LE_JOIN_REQUEST,        "LE_JOIN_REQUEST" },
177   { LE_JOIN_RESPONSE,       "LE_JOIN_RESPONSE" },
178   { READY_QUERY,            "READY_QUERY" },
179   { READY_IND,              "READY_IND" },
180   { LE_REGISTER_REQUEST,    "LE_REGISTER_REQUEST" },
181   { LE_REGISTER_RESPONSE,   "LE_REGISTER_RESPONSE" },
182   { LE_UNREGISTER_REQUEST,  "LE_UNREGISTER_REQUEST" },
183   { LE_UNREGISTER_RESPONSE, "LE_UNREGISTER_RESPONSE" },
184   { LE_ARP_REQUEST,         "LE_ARP_REQUEST" },
185   { LE_ARP_RESPONSE,        "LE_ARP_RESPONSE" },
186   { LE_FLUSH_REQUEST,       "LE_FLUSH_REQUEST" },
187   { LE_FLUSH_RESPONSE,      "LE_FLUSH_RESPONSE" },
188   { LE_NARP_REQUEST,        "LE_NARP_REQUEST" },
189   { LE_TOPOLOGY_REQUEST,    "LE_TOPOLOGY_REQUEST" },
190   { LE_VERIFY_REQUEST,      "LE_VERIFY_REQUEST" },
191   { LE_VERIFY_RESPONSE,     "LE_VERIFY_RESPONSE" },
192   { 0,                      NULL }
193 };
194
195 /* LE Control statuses */
196 static const value_string le_control_status_vals[] = {
197   { 0,  "Success" },
198   { 1,  "Version not supported" },
199   { 2,  "Invalid request parameters" },
200   { 4,  "Duplicate LAN destination registration" },
201   { 5,  "Duplicate ATM address" },
202   { 6,  "Insufficient resources to grant request" },
203   { 7,  "Access denied" },
204   { 8,  "Invalid REQUESTOR-ID" },
205   { 9,  "Invalid LAN destination" },
206   { 10, "Invalid ATM address" },
207   { 20, "No configuration" },
208   { 21, "LE_CONFIGURE error" },
209   { 22, "Insufficient information" },
210   { 24, "TLV not found" },
211   { 0,  NULL }
212 };
213
214 /* LE Control LAN destination tags */
215 #define TAG_NOT_PRESENT         0x0000
216 #define TAG_MAC_ADDRESS         0x0001
217 #define TAG_ROUTE_DESCRIPTOR    0x0002
218
219 static const value_string le_control_landest_tag_vals[] = {
220   { TAG_NOT_PRESENT,       "Not present" },
221   { TAG_MAC_ADDRESS,       "MAC address" },
222   { TAG_ROUTE_DESCRIPTOR,  "Route descriptor" },
223   { 0,                     NULL }
224 };
225
226 /* LE Control LAN types */
227 #define LANT_UNSPEC     0x00
228 #define LANT_802_3      0x01
229 #define LANT_802_5      0x02
230
231 static const value_string le_control_lan_type_vals[] = {
232   { LANT_UNSPEC, "Unspecified" },
233   { LANT_802_3,  "Ethernet/802.3" },
234   { LANT_802_5,  "802.5" },
235   { 0,           NULL }
236 };
237
238 static const value_string le_control_frame_size_vals[] = {
239   { 0x00, "Unspecified" },
240   { 0x01, "1516/1528/1580/1592" },
241   { 0x02, "4544/4556/1580/1592" },
242   { 0x03, "9234/9246" },
243   { 0x04, "18190/18202" },
244   { 0,    NULL }
245 };
246
247 static const value_string atm_channel_vals[] = {
248   { 0, "DTE->DCE" },
249   { 1, "DCE->DTE" },
250   { 0,    NULL }
251 };
252
253 static const true_false_string tfs_remote_local = { "Remote", "Local" };
254 static const true_false_string tfs_low_high_priority = { "Low priority", "High priority" };
255
256
257 static void
258 dissect_le_client(tvbuff_t *tvb, proto_tree *tree)
259 {
260   proto_item *ti;
261   proto_tree *lane_tree;
262
263   if (tree) {
264     ti = proto_tree_add_protocol_format(tree, proto_atm_lane, tvb, 0, 2, "ATM LANE");
265     lane_tree = proto_item_add_subtree(ti, ett_atm_lane);
266
267     proto_tree_add_item(lane_tree, hf_atm_le_client_client, tvb, 0, 2, ENC_BIG_ENDIAN );
268   }
269 }
270
271 static void
272 dissect_lan_destination(tvbuff_t *tvb, int offset, const char *type, proto_tree *tree)
273 {
274   proto_item *td;
275   proto_tree *dest_tree;
276   guint16     tag;
277   proto_tree *rd_tree;
278
279   dest_tree = proto_tree_add_subtree_format(tree, tvb, offset, 8,
280                                     ett_atm_lane_lc_lan_dest, NULL, "%s LAN destination", type);
281   tag = tvb_get_ntohs(tvb, offset);
282   proto_tree_add_item(dest_tree, hf_atm_lan_destination_tag, tvb, offset, 2, ENC_BIG_ENDIAN );
283   offset += 2;
284
285   switch (tag) {
286
287   case TAG_MAC_ADDRESS:
288     proto_tree_add_item(dest_tree, hf_atm_lan_destination_mac, tvb, offset, 6, ENC_NA);
289     break;
290
291   case TAG_ROUTE_DESCRIPTOR:
292     offset += 4;
293     td = proto_tree_add_item(dest_tree, hf_atm_lan_destination_route_desc, tvb, offset, 2, ENC_LITTLE_ENDIAN);
294     rd_tree = proto_item_add_subtree(td, ett_atm_lane_lc_lan_dest_rd);
295     proto_tree_add_item(rd_tree, hf_atm_lan_destination_lan_id, tvb, offset, 2, ENC_LITTLE_ENDIAN);
296     proto_tree_add_item(rd_tree, hf_atm_lan_destination_bridge_num, tvb, offset, 2, ENC_LITTLE_ENDIAN);
297     break;
298   }
299 }
300
301 /*
302  * TLV values in LE Control frames.
303  */
304 #define TLV_TYPE(oui, ident)            (((oui) << 8) | (ident))
305
306 #define LE_CONTROL_TIMEOUT              TLV_TYPE(OUI_ATM_FORUM, 0x01)
307 #define LE_MAX_UNK_FRAME_COUNT          TLV_TYPE(OUI_ATM_FORUM, 0x02)
308 #define LE_MAX_UNK_FRAME_TIME           TLV_TYPE(OUI_ATM_FORUM, 0x03)
309 #define LE_VCC_TIMEOUT_PERIOD           TLV_TYPE(OUI_ATM_FORUM, 0x04)
310 #define LE_MAX_RETRY_COUNT              TLV_TYPE(OUI_ATM_FORUM, 0x05)
311 #define LE_AGING_TIME                   TLV_TYPE(OUI_ATM_FORUM, 0x06)
312 #define LE_FORWARD_DELAY_TIME           TLV_TYPE(OUI_ATM_FORUM, 0x07)
313 #define LE_EXPECTED_ARP_RESPONSE_TIME   TLV_TYPE(OUI_ATM_FORUM, 0x08)
314 #define LE_FLUSH_TIMEOUT                TLV_TYPE(OUI_ATM_FORUM, 0x09)
315 #define LE_PATH_SWITCHING_DELAY         TLV_TYPE(OUI_ATM_FORUM, 0x0A)
316 #define LE_LOCAL_SEGMENT_ID             TLV_TYPE(OUI_ATM_FORUM, 0x0B)
317 #define LE_MCAST_SEND_VCC_TYPE          TLV_TYPE(OUI_ATM_FORUM, 0x0C)
318 #define LE_MCAST_SEND_VCC_AVGRATE       TLV_TYPE(OUI_ATM_FORUM, 0x0D)
319 #define LE_MCAST_SEND_VCC_PEAKRATE      TLV_TYPE(OUI_ATM_FORUM, 0x0E)
320 #define LE_CONN_COMPLETION_TIMER        TLV_TYPE(OUI_ATM_FORUM, 0x0F)
321 #define LE_CONFIG_FRAG_INFO             TLV_TYPE(OUI_ATM_FORUM, 0x10)
322 #define LE_LAYER_3_ADDRESS              TLV_TYPE(OUI_ATM_FORUM, 0x11)
323 #define LE_ELAN_ID                      TLV_TYPE(OUI_ATM_FORUM, 0x12)
324 #define LE_SERVICE_CATEGORY             TLV_TYPE(OUI_ATM_FORUM, 0x13)
325 #define LE_LLC_MUXED_ATM_ADDRESS        TLV_TYPE(OUI_ATM_FORUM, 0x2B)
326 #define LE_X5_ADJUSTMENT                TLV_TYPE(OUI_ATM_FORUM, 0x2C)
327 #define LE_PREFERRED_LES                TLV_TYPE(OUI_ATM_FORUM, 0x2D)
328
329 static const value_string le_tlv_type_vals[] = {
330   { LE_CONTROL_TIMEOUT,           "Control Time-out" },
331   { LE_MAX_UNK_FRAME_COUNT,       "Maximum Unknown Frame Count" },
332   { LE_MAX_UNK_FRAME_TIME,        "Maximum Unknown Frame Time" },
333   { LE_VCC_TIMEOUT_PERIOD,        "VCC Time-out" },
334   { LE_MAX_RETRY_COUNT,           "Maximum Retry Count" },
335   { LE_AGING_TIME,                "Aging Time" },
336   { LE_FORWARD_DELAY_TIME,        "Forwarding Delay Time" },
337   { LE_EXPECTED_ARP_RESPONSE_TIME, "Expected LE_ARP Response Time" },
338   { LE_FLUSH_TIMEOUT,             "Flush Time-out" },
339   { LE_PATH_SWITCHING_DELAY,      "Path Switching Delay" },
340   { LE_LOCAL_SEGMENT_ID,          "Local Segment ID" },
341   { LE_MCAST_SEND_VCC_TYPE,       "Mcast Send VCC Type" },
342   { LE_MCAST_SEND_VCC_AVGRATE,    "Mcast Send VCC AvgRate" },
343   { LE_MCAST_SEND_VCC_PEAKRATE,   "Mcast Send VCC PeakRate" },
344   { LE_CONN_COMPLETION_TIMER,     "Connection Completion Timer" },
345   { LE_CONFIG_FRAG_INFO,          "Config Frag Info" },
346   { LE_LAYER_3_ADDRESS,           "Layer 3 Address" },
347   { LE_ELAN_ID,                   "ELAN ID" },
348   { LE_SERVICE_CATEGORY,          "Service Category" },
349   { LE_LLC_MUXED_ATM_ADDRESS,     "LLC-muxed ATM Address" },
350   { LE_X5_ADJUSTMENT,             "X5 Adjustment" },
351   { LE_PREFERRED_LES,             "Preferred LES" },
352   { 0,                            NULL },
353 };
354
355 static void
356 dissect_le_control_tlvs(tvbuff_t *tvb, int offset, guint num_tlvs,
357                         proto_tree *tree)
358 {
359   guint32     tlv_type;
360   guint8      tlv_length;
361   proto_tree *tlv_tree;
362
363   while (num_tlvs != 0) {
364     tlv_type = tvb_get_ntohl(tvb, offset);
365     tlv_length = tvb_get_guint8(tvb, offset+4);
366     tlv_tree = proto_tree_add_subtree_format(tree, tvb, offset, 5+tlv_length, ett_atm_lane_lc_tlv, NULL,
367                                                 "TLV type: %s", val_to_str(tlv_type, le_tlv_type_vals, "Unknown (0x%08x)"));
368     proto_tree_add_item(tlv_tree, hf_atm_le_control_tlv_type, tvb, offset, 4, ENC_BIG_ENDIAN);
369     proto_tree_add_item(tlv_tree, hf_atm_le_control_tlv_length, tvb, offset+4, 1, ENC_BIG_ENDIAN);
370     offset += 5+tlv_length;
371     num_tlvs--;
372   }
373 }
374
375 static void
376 dissect_le_configure_join_frame(tvbuff_t *tvb, int offset, proto_tree *tree)
377 {
378   guint8 num_tlvs;
379   guint8 name_size;
380
381   dissect_lan_destination(tvb, offset, "Source", tree);
382   offset += 8;
383
384   dissect_lan_destination(tvb, offset, "Target", tree);
385   offset += 8;
386
387   proto_tree_add_item(tree, hf_atm_source_atm, tvb, offset, 20, ENC_NA);
388   offset += 20;
389
390   proto_tree_add_item(tree, hf_atm_le_configure_join_frame_lan_type, tvb, offset, 1, ENC_NA);
391   offset += 1;
392
393   proto_tree_add_item(tree, hf_atm_le_configure_join_frame_max_frame_size, tvb, offset, 1, ENC_NA);
394   offset += 1;
395
396   num_tlvs = tvb_get_guint8(tvb, offset);
397   proto_tree_add_item(tree, hf_atm_le_configure_join_frame_num_tlvs, tvb, offset, 1, ENC_NA);
398   offset += 1;
399
400   name_size = tvb_get_guint8(tvb, offset);
401   proto_tree_add_item(tree, hf_atm_le_configure_join_frame_elan_name_size, tvb, offset, 1, ENC_NA);
402   offset += 1;
403
404   proto_tree_add_item(tree, hf_atm_target_atm, tvb, offset, 20, ENC_NA);
405   offset += 20;
406
407   if (name_size > 32)
408     name_size = 32;
409   if (name_size != 0) {
410     proto_tree_add_item(tree, hf_atm_le_configure_join_frame_elan_name, tvb, offset, name_size, ENC_NA);
411   }
412   offset += 32;
413
414   dissect_le_control_tlvs(tvb, offset, num_tlvs, tree);
415 }
416
417 static void
418 dissect_le_registration_frame(tvbuff_t *tvb, int offset, proto_tree *tree)
419 {
420   guint8 num_tlvs;
421
422   dissect_lan_destination(tvb, offset, "Source", tree);
423   offset += 8;
424
425   dissect_lan_destination(tvb, offset, "Target", tree);
426   offset += 8;
427
428   proto_tree_add_item(tree, hf_atm_source_atm, tvb, offset, 20, ENC_NA);
429   offset += 20;
430
431   proto_tree_add_item(tree, hf_atm_reserved, tvb, offset, 2, ENC_NA);
432   offset += 2;
433
434   num_tlvs = tvb_get_guint8(tvb, offset);
435   proto_tree_add_item(tree, hf_atm_le_registration_frame_num_tlvs, tvb, offset, 1, ENC_NA);
436   offset += 1;
437
438   proto_tree_add_item(tree, hf_atm_reserved, tvb, offset, 53, ENC_NA);
439   offset += 53;
440
441   dissect_le_control_tlvs(tvb, offset, num_tlvs, tree);
442 }
443
444 static void
445 dissect_le_arp_frame(tvbuff_t *tvb, int offset, proto_tree *tree)
446 {
447   guint8 num_tlvs;
448
449   dissect_lan_destination(tvb, offset, "Source", tree);
450   offset += 8;
451
452   dissect_lan_destination(tvb, offset, "Target", tree);
453   offset += 8;
454
455   proto_tree_add_item(tree, hf_atm_source_atm, tvb, offset, 20, ENC_NA);
456   offset += 20;
457
458   proto_tree_add_item(tree, hf_atm_reserved, tvb, offset, 2, ENC_NA);
459   offset += 2;
460
461   num_tlvs = tvb_get_guint8(tvb, offset);
462   proto_tree_add_item(tree, hf_atm_le_arp_frame_num_tlvs, tvb, offset, 1, ENC_NA);
463   offset += 1;
464
465   proto_tree_add_item(tree, hf_atm_reserved, tvb, offset, 1, ENC_NA);
466   offset += 1;
467
468   proto_tree_add_item(tree, hf_atm_target_atm, tvb, offset, 20, ENC_NA);
469   offset += 20;
470
471   proto_tree_add_item(tree, hf_atm_reserved, tvb, offset, 32, ENC_NA);
472   offset += 32;
473
474   dissect_le_control_tlvs(tvb, offset, num_tlvs, tree);
475 }
476
477 static void
478 dissect_le_verify_frame(tvbuff_t *tvb, int offset, proto_tree *tree)
479 {
480   guint8 num_tlvs;
481
482   proto_tree_add_item(tree, hf_atm_reserved, tvb, offset, 38, ENC_NA);
483   offset += 38;
484
485   num_tlvs = tvb_get_guint8(tvb, offset);
486   proto_tree_add_item(tree, hf_atm_le_verify_frame_num_tlvs, tvb, offset, 1, ENC_NA);
487   offset += 1;
488
489   proto_tree_add_item(tree, hf_atm_reserved, tvb, offset, 1, ENC_NA);
490   offset += 1;
491
492   proto_tree_add_item(tree, hf_atm_target_atm, tvb, offset, 20, ENC_NA);
493   offset += 20;
494
495   proto_tree_add_item(tree, hf_atm_reserved, tvb, offset, 32, ENC_NA);
496   offset += 32;
497
498   dissect_le_control_tlvs(tvb, offset, num_tlvs, tree);
499 }
500
501 static int
502 dissect_le_flush_frame(tvbuff_t *tvb, int offset, proto_tree *tree)
503 {
504   dissect_lan_destination(tvb, offset, "Source", tree);
505   offset += 8;
506
507   dissect_lan_destination(tvb, offset, "Target", tree);
508   offset += 8;
509
510   proto_tree_add_item(tree, hf_atm_source_atm, tvb, offset, 20, ENC_NA);
511   offset += 20;
512
513   proto_tree_add_item(tree, hf_atm_reserved, tvb, offset, 4, ENC_NA);
514   offset += 4;
515
516   proto_tree_add_item(tree, hf_atm_target_atm, tvb, offset, 20, ENC_NA);
517   offset += 20;
518
519   proto_tree_add_item(tree, hf_atm_reserved, tvb, offset, 32, ENC_NA);
520   offset += 32;
521
522   return offset;
523 }
524
525 static void
526 dissect_le_control(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
527 {
528   proto_item *ti;
529   proto_tree *lane_tree = NULL;
530   int         offset    = 0;
531   proto_item *tf;
532   proto_tree *flags_tree;
533   guint16     opcode;
534
535   col_set_str(pinfo->cinfo, COL_INFO, "LE Control");
536
537   if (tree) {
538     ti = proto_tree_add_protocol_format(tree, proto_atm_lane, tvb, offset, 108, "ATM LANE");
539     lane_tree = proto_item_add_subtree(ti, ett_atm_lane);
540
541     proto_tree_add_item(lane_tree, hf_atm_le_control_marker, tvb, offset, 2, ENC_BIG_ENDIAN );
542   }
543   offset += 2;
544
545   if (tree) {
546     proto_tree_add_item(lane_tree, hf_atm_le_control_protocol, tvb, offset, 1, ENC_BIG_ENDIAN );
547
548   }
549   offset += 1;
550
551   if (tree) {
552     proto_tree_add_item(lane_tree, hf_atm_le_control_version, tvb, offset, 1, ENC_BIG_ENDIAN );
553   }
554   offset += 1;
555
556   opcode = tvb_get_ntohs(tvb, offset);
557   col_append_fstr(pinfo->cinfo, COL_INFO, ": %s",
558                   val_to_str(opcode, le_control_opcode_vals,
559                              "Unknown opcode (0x%04X)"));
560
561   if (tree) {
562     proto_tree_add_item(lane_tree, hf_atm_le_control_opcode, tvb, offset, 2, ENC_BIG_ENDIAN );
563   }
564   offset += 2;
565
566   if (opcode == READY_QUERY || opcode == READY_IND) {
567     /* There's nothing more in this packet. */
568     return;
569   }
570
571   if (tree) {
572     if (opcode & 0x0100) {
573       /* Response; decode status. */
574       proto_tree_add_item(lane_tree, hf_atm_le_control_status, tvb, offset, 2, ENC_BIG_ENDIAN );
575     }
576     offset += 2;
577
578     proto_tree_add_item(lane_tree, hf_atm_le_control_transaction_id, tvb, offset, 4, ENC_BIG_ENDIAN );
579     offset += 4;
580
581     proto_tree_add_item(lane_tree, hf_atm_le_control_requester_lecid, tvb, offset, 2, ENC_BIG_ENDIAN );
582     offset += 2;
583
584     tf = proto_tree_add_item(lane_tree, hf_atm_le_control_flags, tvb, offset, 2, ENC_BIG_ENDIAN );
585     flags_tree = proto_item_add_subtree(tf, ett_atm_lane_lc_flags);
586
587     switch (opcode) {
588
589     case LE_CONFIGURE_REQUEST:
590     case LE_CONFIGURE_RESPONSE:
591       proto_tree_add_item(flags_tree, hf_atm_le_control_flag_v2_capable, tvb, offset, 2, ENC_BIG_ENDIAN);
592       offset += 2;
593       dissect_le_configure_join_frame(tvb, offset, lane_tree);
594       break;
595
596     case LE_JOIN_REQUEST:
597     case LE_JOIN_RESPONSE:
598       proto_tree_add_item(flags_tree, hf_atm_le_control_flag_v2_capable, tvb, offset, 2, ENC_BIG_ENDIAN);
599       if (opcode == LE_JOIN_REQUEST) {
600         proto_tree_add_item(flags_tree, hf_atm_le_control_flag_selective_multicast, tvb, offset, 2, ENC_BIG_ENDIAN);
601       } else {
602         proto_tree_add_item(flags_tree, hf_atm_le_control_flag_v2_required, tvb, offset, 2, ENC_BIG_ENDIAN);
603       }
604
605       proto_tree_add_item(flags_tree, hf_atm_le_control_flag_proxy, tvb, offset, 2, ENC_BIG_ENDIAN);
606       proto_tree_add_item(flags_tree, hf_atm_le_control_flag_exclude_explorer_frames, tvb, offset, 2, ENC_BIG_ENDIAN);
607
608       offset += 2;
609       dissect_le_configure_join_frame(tvb, offset, lane_tree);
610       break;
611
612     case LE_REGISTER_REQUEST:
613     case LE_REGISTER_RESPONSE:
614     case LE_UNREGISTER_REQUEST:
615     case LE_UNREGISTER_RESPONSE:
616       offset += 2;
617       dissect_le_registration_frame(tvb, offset, lane_tree);
618       break;
619
620     case LE_ARP_REQUEST:
621     case LE_ARP_RESPONSE:
622     case LE_NARP_REQUEST:
623       if (opcode != LE_NARP_REQUEST) {
624         proto_tree_add_item(flags_tree, hf_atm_le_control_flag_address, tvb, offset, 2, ENC_BIG_ENDIAN);
625       }
626       offset += 2;
627       dissect_le_arp_frame(tvb, offset, lane_tree);
628       break;
629
630     case LE_TOPOLOGY_REQUEST:
631         proto_tree_add_item(flags_tree, hf_atm_le_control_topology_change, tvb, offset, 2, ENC_BIG_ENDIAN);
632         offset += 2;
633         proto_tree_add_item(flags_tree, hf_atm_reserved, tvb, offset, 92, ENC_NA);
634       break;
635
636     case LE_VERIFY_REQUEST:
637     case LE_VERIFY_RESPONSE:
638       offset += 2;
639       dissect_le_verify_frame(tvb, offset, lane_tree);
640       break;
641
642     case LE_FLUSH_REQUEST:
643     case LE_FLUSH_RESPONSE:
644       offset += 2;
645       dissect_le_flush_frame(tvb, offset, lane_tree);
646       break;
647     }
648   }
649 }
650
651 static gboolean
652 capture_lane(const guchar *pd, int offset _U_,
653     int len, capture_packet_info_t *cpinfo, const union wtap_pseudo_header *pseudo_header)
654 {
655   /* Is it LE Control, 802.3, 802.5, or "none of the above"? */
656   return try_capture_dissector("atm_lane", pseudo_header->atm.subtype, pd, 2, len, cpinfo, pseudo_header);
657 }
658
659 static int
660 dissect_lane(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
661 {
662   struct atm_phdr *atm_info = (struct atm_phdr *)data;
663   tvbuff_t *next_tvb;
664   tvbuff_t *next_tvb_le_client;
665
666   col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATM LANE");
667
668   /* Is it LE Control, 802.3, 802.5, or "none of the above"? */
669   switch (atm_info->subtype) {
670
671   case TRAF_ST_LANE_LE_CTRL:
672     dissect_le_control(tvb, pinfo, tree);
673     break;
674
675   case TRAF_ST_LANE_802_3:
676   case TRAF_ST_LANE_802_3_MC:
677     col_set_str(pinfo->cinfo, COL_INFO, "LE Client - Ethernet/802.3");
678     dissect_le_client(tvb, tree);
679
680     /* Dissect as Ethernet */
681     next_tvb_le_client  = tvb_new_subset_remaining(tvb, 2);
682     call_dissector(eth_withoutfcs_handle, next_tvb_le_client, pinfo, tree);
683     break;
684
685   case TRAF_ST_LANE_802_5:
686   case TRAF_ST_LANE_802_5_MC:
687     col_set_str(pinfo->cinfo, COL_INFO, "LE Client - 802.5");
688     dissect_le_client(tvb, tree);
689
690     /* Dissect as Token-Ring */
691     next_tvb_le_client  = tvb_new_subset_remaining(tvb, 2);
692     call_dissector(tr_handle, next_tvb_le_client, pinfo, tree);
693     break;
694
695   default:
696     /* Dump it as raw data. */
697     col_set_str(pinfo->cinfo, COL_INFO, "Unknown LANE traffic type");
698     next_tvb            = tvb_new_subset_remaining(tvb, 0);
699     call_data_dissector(next_tvb, pinfo, tree);
700     break;
701   }
702   return tvb_captured_length(tvb);
703 }
704
705 static int
706 dissect_ilmi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
707 {
708   return dissect_snmp_pdu(tvb, 0, pinfo, tree, proto_ilmi, ett_ilmi, FALSE);
709 }
710
711 /* AAL types */
712 static const value_string aal_vals[] = {
713   { AAL_UNKNOWN,            "Unknown AAL" },
714   { AAL_1,                  "AAL1" },
715   { AAL_2,                  "AAL2" },
716   { AAL_3_4,                "AAL3/4" },
717   { AAL_5,                  "AAL5" },
718   { AAL_USER,               "User AAL" },
719   { AAL_SIGNALLING,         "Signalling AAL" },
720   { AAL_OAMCELL,            "OAM cell" },
721   { 0,              NULL }
722 };
723
724 /* AAL5 higher-level traffic types */
725 static const value_string aal5_hltype_vals[] = {
726   { TRAF_UNKNOWN,           "Unknown traffic type" },
727   { TRAF_LLCMX,             "LLC multiplexed" },
728   { TRAF_VCMX,              "VC multiplexed" },
729   { TRAF_LANE,              "LANE" },
730   { TRAF_ILMI,              "ILMI" },
731   { TRAF_FR,                "Frame Relay" },
732   { TRAF_SPANS,             "FORE SPANS" },
733   { TRAF_IPSILON,           "Ipsilon" },
734   { TRAF_GPRS_NS,           "GPRS NS" },
735   { TRAF_SSCOP,             "SSCOP" },
736   { 0,              NULL }
737 };
738
739 /* Traffic subtypes for VC multiplexed traffic */
740 static const value_string vcmx_type_vals[] = {
741   { TRAF_ST_UNKNOWN,        "Unknown VC multiplexed traffic type" },
742   { TRAF_ST_VCMX_802_3_FCS, "802.3 FCS" },
743   { TRAF_ST_VCMX_802_4_FCS, "802.4 FCS" },
744   { TRAF_ST_VCMX_802_5_FCS, "802.5 FCS" },
745   { TRAF_ST_VCMX_FDDI_FCS,  "FDDI FCS" },
746   { TRAF_ST_VCMX_802_6_FCS, "802.6 FCS" },
747   { TRAF_ST_VCMX_802_3,     "802.3" },
748   { TRAF_ST_VCMX_802_4,     "802.4" },
749   { TRAF_ST_VCMX_802_5,     "802.5" },
750   { TRAF_ST_VCMX_FDDI,      "FDDI" },
751   { TRAF_ST_VCMX_802_6,     "802.6" },
752   { TRAF_ST_VCMX_FRAGMENTS, "Fragments" },
753   { TRAF_ST_VCMX_BPDU,      "BPDU" },
754   { 0,                   NULL }
755 };
756
757 /* Traffic subtypes for LANE traffic */
758 static const value_string lane_type_vals[] = {
759   { TRAF_ST_UNKNOWN,        "Unknown LANE traffic type" },
760   { TRAF_ST_LANE_LE_CTRL,   "LE Control" },
761   { TRAF_ST_LANE_802_3,     "802.3" },
762   { TRAF_ST_LANE_802_5,     "802.5" },
763   { TRAF_ST_LANE_802_3_MC,  "802.3 multicast" },
764   { TRAF_ST_LANE_802_5_MC,  "802.5 multicast" },
765   { 0,                     NULL }
766 };
767
768 /* Traffic subtypes for Ipsilon traffic */
769 static const value_string ipsilon_type_vals[] = {
770   { TRAF_ST_UNKNOWN,        "Unknown Ipsilon traffic type" },
771   { TRAF_ST_IPSILON_FT0,    "Flow type 0" },
772   { TRAF_ST_IPSILON_FT1,    "Flow type 1" },
773   { TRAF_ST_IPSILON_FT2,    "Flow type 2" },
774   { 0,                NULL }
775 };
776
777 static gboolean
778 capture_atm(const guchar *pd, int offset,
779     int len, capture_packet_info_t *cpinfo, const union wtap_pseudo_header *pseudo_header)
780 {
781   if (pseudo_header->atm.aal == AAL_5) {
782     return try_capture_dissector("atm.aal5.type", pseudo_header->atm.type, pd, offset, len, cpinfo, pseudo_header);
783   }
784   return FALSE;
785 }
786
787 static void
788 dissect_reassembled_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
789     proto_item *atm_ti, proto_tree *atm_tree, gboolean truncated,
790     struct atm_phdr *atm_info, gboolean pseudowire_mode)
791 {
792   guint     length, reported_length;
793   guint16   aal5_length;
794   int       pad_length;
795   tvbuff_t *next_tvb;
796   guint32   crc;
797   guint32   calc_crc;
798   gboolean  decoded;
799
800   /*
801    * This is reassembled traffic, so the cell headers are missing;
802    * show the traffic type for AAL5 traffic, and the VPI and VCI,
803    * from the pseudo-header.
804    */
805   if (atm_info->aal == AAL_5) {
806     proto_tree_add_uint(atm_tree, hf_atm_traffic_type, tvb, 0, 0, atm_info->type);
807
808     switch (atm_info->type) {
809
810     case TRAF_VCMX:
811       proto_tree_add_uint(atm_tree, hf_atm_traffic_vcmx, tvb, 0, 0, atm_info->subtype);
812       break;
813
814     case TRAF_LANE:
815       proto_tree_add_uint(atm_tree, hf_atm_traffic_lane, tvb, 0, 0, atm_info->subtype);
816       break;
817
818     case TRAF_IPSILON:
819       proto_tree_add_uint(atm_tree, hf_atm_traffic_ipsilon, tvb, 0, 0, atm_info->subtype);
820       break;
821     }
822   }
823   if (!pseudowire_mode) {
824     proto_tree_add_uint(atm_tree, hf_atm_vpi, tvb, 0, 0, atm_info->vpi);
825     proto_tree_add_uint(atm_tree, hf_atm_vci, tvb, 0, 0, atm_info->vci);
826
827     /* Also show vpi/vci in info column */
828     col_append_fstr(pinfo->cinfo, COL_INFO, " VPI=%u, VCI=%u",
829                     atm_info->vpi, atm_info->vci);
830   }
831
832   next_tvb = tvb;
833   if (truncated || atm_info->flags & ATM_REASSEMBLY_ERROR) {
834     /*
835      * The packet data does not include stuff such as the AAL5
836      * trailer, either because it was explicitly left out or because
837      * reassembly failed.
838      */
839     if (atm_info->cells != 0) {
840       /*
841        * If the cell count is 0, assume it means we don't know how
842        * many cells it was.
843        *
844        * XXX - also assume it means we don't know what was in the AAL5
845        * trailer.  We may, however, find some capture program that can
846        * give us the AAL5 trailer information but not the cell count,
847        * in which case we need some other way of indicating whether we
848        * have the AAL5 trailer information.
849        */
850       if (tree) {
851         proto_tree_add_uint(atm_tree, hf_atm_cells, tvb, 0, 0, atm_info->cells);
852         proto_tree_add_uint(atm_tree, hf_atm_aal5_uu, tvb, 0, 0, atm_info->aal5t_u2u >> 8);
853         proto_tree_add_uint(atm_tree, hf_atm_aal5_cpi, tvb, 0, 0, atm_info->aal5t_u2u & 0xFF);
854         proto_tree_add_uint(atm_tree, hf_atm_aal5_len, tvb, 0, 0, atm_info->aal5t_len);
855         proto_tree_add_uint(atm_tree, hf_atm_aal5_crc, tvb, 0, 0, atm_info->aal5t_chksum);
856       }
857     }
858   } else {
859     /*
860      * The packet data includes stuff such as the AAL5 trailer, if
861      * it wasn't cut off by the snapshot length, and ATM reassembly
862      * succeeded.
863      * Decode the trailer, if present, and then chop it off.
864      */
865     length = tvb_captured_length(tvb);
866     reported_length = tvb_reported_length(tvb);
867     if ((reported_length % 48) == 0) {
868       /*
869        * Reported length is a multiple of 48, so we can presumably
870        * divide it by 48 to get the number of cells.
871        */
872       proto_tree_add_uint(atm_tree, hf_atm_cells, tvb, 0, 0, reported_length/48);
873     }
874     if ((atm_info->aal == AAL_5 || atm_info->aal == AAL_SIGNALLING) &&
875         length >= reported_length) {
876       /*
877        * XXX - what if the packet is truncated?  Can that happen?
878        * What if you capture with Windows Sniffer on an ATM link
879        * and tell it not to save the entire packet?  What happens
880        * to the trailer?
881        */
882       aal5_length = tvb_get_ntohs(tvb, length - 6);
883
884       /*
885        * Check for sanity in the AAL5 length.  It must be > 0
886        * and must be less than the amount of space left after
887        * we remove the trailer.
888        *
889        * If it's not sane, assume we don't have a trailer.
890        */
891       if (aal5_length > 0 && aal5_length <= length - 8) {
892         /*
893          * How much padding is there?
894          */
895         pad_length = length - aal5_length - 8;
896
897         /*
898          * There is no reason for more than 47 bytes of padding.
899          * The most padding you can have would be 7 bytes at the
900          * end of the next-to-last cell (8 bytes after the end of
901          * the data means you can fit the trailer in that cell),
902          * plus 40 bytes in the last cell (with the last 8 bytes
903          * being padding).
904          *
905          * If there's more than 47 bytes of padding, assume we don't
906          * have a trailer.
907          */
908         if (pad_length <= 47) {
909           if (tree) {
910             proto_item *ti;
911
912             if (pad_length > 0) {
913               proto_tree_add_item(atm_tree, hf_atm_padding, tvb, aal5_length, pad_length, ENC_NA);
914             }
915
916             proto_tree_add_item(atm_tree, hf_atm_aal5_uu, tvb, length - 8, 1, ENC_BIG_ENDIAN);
917             proto_tree_add_item(atm_tree, hf_atm_aal5_cpi, tvb, length - 7, 1, ENC_BIG_ENDIAN);
918             proto_tree_add_item(atm_tree, hf_atm_aal5_len, tvb, length - 6, 2, ENC_BIG_ENDIAN);
919
920             crc = tvb_get_ntohl(tvb, length - 4);
921             calc_crc = crc32_mpeg2_tvb(tvb, length);
922             ti = proto_tree_add_uint(atm_tree, hf_atm_aal5_crc, tvb, length - 4, 4, crc);
923             proto_item_append_text(ti, (calc_crc == 0xC704DD7B) ? " (correct)" : " (incorrect)");
924           }
925           next_tvb = tvb_new_subset_length(tvb, 0, aal5_length);
926         }
927       }
928     }
929   }
930
931   decoded = FALSE;
932   /*
933    * Don't try to dissect the payload of PDUs with a reassembly
934    * error.
935    */
936   switch (atm_info->aal) {
937
938   case AAL_SIGNALLING:
939     if (!(atm_info->flags & ATM_REASSEMBLY_ERROR)) {
940       call_dissector(sscop_handle, next_tvb, pinfo, tree);
941       decoded = TRUE;
942     }
943     break;
944
945   case AAL_5:
946     if (!(atm_info->flags & ATM_REASSEMBLY_ERROR)) {
947       if (dissector_try_uint_new(atm_type_aal5_table, atm_info->type, next_tvb, pinfo, tree, TRUE, atm_info))
948       {
949         decoded = TRUE;
950       }
951       else
952       {
953         if (tvb_reported_length(next_tvb) > 7) /* sizeof(octet) */
954         {
955           guint8 octet[8];
956           tvb_memcpy(next_tvb, octet, 0, sizeof(octet));
957
958           if (octet[0] == 0xaa
959            && octet[1] == 0xaa
960            && octet[2] == 0x03) /* LLC SNAP as per RFC2684 */
961           {
962             call_dissector(llc_handle, next_tvb, pinfo, tree);
963             decoded = TRUE;
964           }
965           else if ((pntoh16(octet) & 0xff) == PPP_IP)
966           {
967             call_dissector(ppp_handle, next_tvb, pinfo, tree);
968             decoded = TRUE;
969           }
970           else if (pntoh16(octet) == 0x00)
971           {
972             /*
973              * Assume VC multiplexed bridged Ethernet.
974              * Whether there's an FCS is an option negotiated
975              * over the VC, so we call the "do heuristic checks
976              * to see if there's an FCS" version of the Ethernet
977              * dissector.
978              *
979              * See RFC 2684 section 6.2 "VC Multiplexing of Bridged
980              * Protocols".
981              */
982             proto_tree_add_item(tree, hf_atm_padding, tvb, 0, 2, ENC_NA);
983             next_tvb = tvb_new_subset_remaining(tvb, 2);
984             call_dissector(eth_maybefcs_handle, next_tvb, pinfo, tree);
985             decoded = TRUE;
986           }
987           else if (octet[2] == 0x03    && /* NLPID */
988                   ((octet[3] == 0xcc   || /* IPv4  */
989                     octet[3] == 0x8e)  || /* IPv6  */
990                    (octet[3] == 0x00   && /* Eth   */
991                     octet[4] == 0x80)))   /* Eth   */
992           {
993             /* assume network interworking with FR 2 byte header */
994             call_dissector(fr_handle, next_tvb, pinfo, tree);
995             decoded = TRUE;
996           }
997           else if (octet[4] == 0x03    && /* NLPID */
998                   ((octet[5] == 0xcc   || /* IPv4  */
999                     octet[5] == 0x8e)  || /* IPv6  */
1000                    (octet[5] == 0x00   && /* Eth   */
1001                     octet[6] == 0x80)))   /* Eth   */
1002           {
1003             /* assume network interworking with FR 4 byte header */
1004             call_dissector(fr_handle, next_tvb, pinfo, tree);
1005             decoded = TRUE;
1006           }
1007           else if (((octet[0] & 0xf0)== 0x40) ||
1008                    ((octet[0] & 0xf0) == 0x60))
1009           {
1010             call_dissector(ip_handle, next_tvb, pinfo, tree);
1011             decoded = TRUE;
1012           }
1013         }
1014       }
1015       break;
1016     }
1017     break;
1018
1019   case AAL_2:
1020     proto_tree_add_uint(atm_tree, hf_atm_cid, tvb, 0, 0,
1021                         atm_info->aal2_cid);
1022     proto_item_append_text(atm_ti, " (vpi=%u vci=%u cid=%u)",
1023                            atm_info->vpi,
1024                            atm_info->vci,
1025                            atm_info->aal2_cid);
1026
1027     if (!(atm_info->flags & ATM_REASSEMBLY_ERROR)) {
1028       if (atm_info->flags & ATM_AAL2_NOPHDR) {
1029         next_tvb = tvb;
1030       } else {
1031         /* Skip first 4 bytes of message
1032            - side
1033            - length
1034            - UUI
1035            Ignoring for now... */
1036         next_tvb = tvb_new_subset_remaining(tvb, 4);
1037       }
1038
1039       if (dissector_try_uint(atm_type_aal2_table, atm_info->type, next_tvb, pinfo, tree))
1040       {
1041         decoded = TRUE;
1042       }
1043     }
1044     break;
1045
1046   default:
1047     /* Dump it as raw data. */
1048     break;
1049   }
1050
1051   if (!decoded) {
1052     /* Dump it as raw data. */
1053     call_data_dissector(next_tvb, pinfo, tree);
1054   }
1055 }
1056
1057 /*
1058  * Charles Michael Heard's HEC code, from
1059  *
1060  *      http://www.cell-relay.com/cell-relay/publications/software/CRC/32bitCRC.tutorial.html
1061  *
1062  * with the syndrome and error position tables initialized with values
1063  * computed by his "gen_syndrome_table()" and "gen_err_posn_table()" routines,
1064  * rather than by calling those routines at run time, and with various data
1065  * type cleanups and changes not to correct the header if a correctible
1066  * error was detected.
1067  */
1068 #define COSET_LEADER    0x055               /* x^6 + x^4 + x^2 + 1  */
1069
1070 static const guint8 syndrome_table[256] = {
1071   0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15,
1072   0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d,
1073   0x70, 0x77, 0x7e, 0x79, 0x6c, 0x6b, 0x62, 0x65,
1074   0x48, 0x4f, 0x46, 0x41, 0x54, 0x53, 0x5a, 0x5d,
1075   0xe0, 0xe7, 0xee, 0xe9, 0xfc, 0xfb, 0xf2, 0xf5,
1076   0xd8, 0xdf, 0xd6, 0xd1, 0xc4, 0xc3, 0xca, 0xcd,
1077   0x90, 0x97, 0x9e, 0x99, 0x8c, 0x8b, 0x82, 0x85,
1078   0xa8, 0xaf, 0xa6, 0xa1, 0xb4, 0xb3, 0xba, 0xbd,
1079   0xc7, 0xc0, 0xc9, 0xce, 0xdb, 0xdc, 0xd5, 0xd2,
1080   0xff, 0xf8, 0xf1, 0xf6, 0xe3, 0xe4, 0xed, 0xea,
1081   0xb7, 0xb0, 0xb9, 0xbe, 0xab, 0xac, 0xa5, 0xa2,
1082   0x8f, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9d, 0x9a,
1083   0x27, 0x20, 0x29, 0x2e, 0x3b, 0x3c, 0x35, 0x32,
1084   0x1f, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0d, 0x0a,
1085   0x57, 0x50, 0x59, 0x5e, 0x4b, 0x4c, 0x45, 0x42,
1086   0x6f, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7d, 0x7a,
1087   0x89, 0x8e, 0x87, 0x80, 0x95, 0x92, 0x9b, 0x9c,
1088   0xb1, 0xb6, 0xbf, 0xb8, 0xad, 0xaa, 0xa3, 0xa4,
1089   0xf9, 0xfe, 0xf7, 0xf0, 0xe5, 0xe2, 0xeb, 0xec,
1090   0xc1, 0xc6, 0xcf, 0xc8, 0xdd, 0xda, 0xd3, 0xd4,
1091   0x69, 0x6e, 0x67, 0x60, 0x75, 0x72, 0x7b, 0x7c,
1092   0x51, 0x56, 0x5f, 0x58, 0x4d, 0x4a, 0x43, 0x44,
1093   0x19, 0x1e, 0x17, 0x10, 0x05, 0x02, 0x0b, 0x0c,
1094   0x21, 0x26, 0x2f, 0x28, 0x3d, 0x3a, 0x33, 0x34,
1095   0x4e, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5c, 0x5b,
1096   0x76, 0x71, 0x78, 0x7f, 0x6a, 0x6d, 0x64, 0x63,
1097   0x3e, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2c, 0x2b,
1098   0x06, 0x01, 0x08, 0x0f, 0x1a, 0x1d, 0x14, 0x13,
1099   0xae, 0xa9, 0xa0, 0xa7, 0xb2, 0xb5, 0xbc, 0xbb,
1100   0x96, 0x91, 0x98, 0x9f, 0x8a, 0x8d, 0x84, 0x83,
1101   0xde, 0xd9, 0xd0, 0xd7, 0xc2, 0xc5, 0xcc, 0xcb,
1102   0xe6, 0xe1, 0xe8, 0xef, 0xfa, 0xfd, 0xf4, 0xf3,
1103 };
1104
1105 #define NO_ERROR_DETECTED   -128
1106 #define UNCORRECTIBLE_ERROR  128
1107
1108 static const int err_posn_table[256] = {
1109   NO_ERROR_DETECTED,      39,
1110   38,                     UNCORRECTIBLE_ERROR,
1111   37,                     UNCORRECTIBLE_ERROR,
1112   UNCORRECTIBLE_ERROR,    31,
1113   36,                     UNCORRECTIBLE_ERROR,
1114   UNCORRECTIBLE_ERROR,    8,
1115   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1116   30,                     UNCORRECTIBLE_ERROR,
1117   35,                     UNCORRECTIBLE_ERROR,
1118   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1119   UNCORRECTIBLE_ERROR,    23,
1120   7,                      UNCORRECTIBLE_ERROR,
1121   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1122   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1123   29,                     UNCORRECTIBLE_ERROR,
1124   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1125   34,                     UNCORRECTIBLE_ERROR,
1126   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1127   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1128   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1129   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1130   22,                     UNCORRECTIBLE_ERROR,
1131   6,                      UNCORRECTIBLE_ERROR,
1132   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1133   UNCORRECTIBLE_ERROR,    0,
1134   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1135   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1136   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1137   28,                     UNCORRECTIBLE_ERROR,
1138   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1139   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1140   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1141   33,                     UNCORRECTIBLE_ERROR,
1142   UNCORRECTIBLE_ERROR,    10,
1143   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1144   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1145   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1146   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1147   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1148   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1149   UNCORRECTIBLE_ERROR,    12,
1150   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1151   21,                     UNCORRECTIBLE_ERROR,
1152   UNCORRECTIBLE_ERROR,    19,
1153   5,                      UNCORRECTIBLE_ERROR,
1154   UNCORRECTIBLE_ERROR,    17,
1155   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1156   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1157   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1158   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1159   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1160   UNCORRECTIBLE_ERROR,    3,
1161   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1162   UNCORRECTIBLE_ERROR,    15,
1163   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1164   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1165   27,                     UNCORRECTIBLE_ERROR,
1166   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1167   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1168   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1169   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1170   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1171   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1172   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1173   32,                     UNCORRECTIBLE_ERROR,
1174   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1175   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1176   9,                      UNCORRECTIBLE_ERROR,
1177   UNCORRECTIBLE_ERROR,    24,
1178   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1179   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1180   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1181   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1182   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1183   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1184   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1185   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1186   UNCORRECTIBLE_ERROR,    1,
1187   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1188   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1189   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1190   11,                     UNCORRECTIBLE_ERROR,
1191   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1192   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1193   20,                     UNCORRECTIBLE_ERROR,
1194   UNCORRECTIBLE_ERROR,    13,
1195   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1196   18,                     UNCORRECTIBLE_ERROR,
1197   4,                      UNCORRECTIBLE_ERROR,
1198   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1199   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1200   16,                     UNCORRECTIBLE_ERROR,
1201   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1202   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1203   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1204   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1205   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1206   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1207   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1208   UNCORRECTIBLE_ERROR,    25,
1209   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1210   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1211   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1212   2,                      UNCORRECTIBLE_ERROR,
1213   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1214   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1215   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1216   14,                     UNCORRECTIBLE_ERROR,
1217   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1218   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1219   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1220   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1221   26,                     UNCORRECTIBLE_ERROR,
1222   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1223   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1224   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1225   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1226   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1227   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1228   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1229   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1230   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1231   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1232   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1233   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1234   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1235   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1236   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1237 };
1238
1239 /*
1240  * Return an indication of whether there was an error in the cell header
1241  * and, if so, where the error was, if it was correctable.
1242  */
1243 static int
1244 get_header_err(const guint8 *cell_header)
1245 {
1246   register guint8 syndrome;
1247   register int    i, err_posn;
1248
1249   syndrome = 0;
1250   for (i = 0;  i < 4;  i++)
1251     syndrome = syndrome_table[syndrome ^ cell_header[i]];
1252   syndrome ^= cell_header[4] ^ COSET_LEADER;
1253
1254   err_posn = err_posn_table [syndrome];
1255
1256   if (err_posn < 0)
1257     return NO_ERROR_DETECTED;
1258   else if (err_posn < 40)
1259     return err_posn;
1260   else
1261     return UNCORRECTIBLE_ERROR;
1262 }
1263
1264 const value_string atm_pt_vals[] = {
1265   { 0, "User data cell, congestion not experienced, SDU-type = 0" },
1266   { 1, "User data cell, congestion not experienced, SDU-type = 1" },
1267   { 2, "User data cell, congestion experienced, SDU-type = 0" },
1268   { 3, "User data cell, congestion experienced, SDU-type = 1" },
1269   { 4, "Segment OAM F5 flow related cell" },
1270   { 5, "End-to-end OAM F5 flow related cell" },
1271   { 6, "VC resource management cell" },
1272   { 0, NULL }
1273 };
1274
1275 static const value_string st_vals[] = {
1276   { 2, "BOM" },
1277   { 0, "COM" },
1278   { 1, "EOM" },
1279   { 3, "SSM" },
1280   { 0, NULL }
1281 };
1282
1283 #define OAM_TYPE_FM     1       /* Fault Management */
1284 #define OAM_TYPE_PM     2       /* Performance Management */
1285 #define OAM_TYPE_AD     8       /* Activation/Deactivation */
1286
1287 static const value_string oam_type_vals[] = {
1288   { OAM_TYPE_FM, "Fault Management" },
1289   { OAM_TYPE_PM, "Performance Management" },
1290   { OAM_TYPE_AD, "Activation/Deactivation" },
1291   { 0,           NULL }
1292 };
1293
1294 static const value_string ft_fm_vals[] = {
1295   { 0, "Alarm Indication Signal" },
1296   { 1, "Far End Receive Failure" },
1297   { 8, "OAM Cell Loopback" },
1298   { 4, "Continuity Check" },
1299   { 0, NULL }
1300 };
1301
1302 static const value_string ft_pm_vals[] = {
1303   { 0, "Forward Monitoring" },
1304   { 1, "Backward Reporting" },
1305   { 2, "Monitoring and Reporting" },
1306   { 0, NULL }
1307 };
1308
1309 static const value_string ft_ad_vals[] = {
1310   { 0, "Performance Monitoring" },
1311   { 1, "Continuity Check" },
1312   { 0, NULL }
1313 };
1314
1315
1316 static void
1317 dissect_atm_cell_payload(tvbuff_t *tvb, int offset, packet_info *pinfo,
1318                          proto_tree *tree, guint aal, gboolean fill_columns)
1319 {
1320   proto_tree *aal_tree;
1321   proto_item *ti;
1322   guint8      octet;
1323   gint        length;
1324   guint16     aal3_4_hdr, crc10;
1325   tvbuff_t   *next_tvb;
1326
1327   switch (aal) {
1328
1329   case AAL_1:
1330     col_set_str(pinfo->cinfo, COL_PROTOCOL, "AAL1");
1331     col_clear(pinfo->cinfo, COL_INFO);
1332     ti = proto_tree_add_item(tree, proto_aal1, tvb, offset, -1, ENC_NA);
1333     aal_tree = proto_item_add_subtree(ti, ett_aal1);
1334     octet = tvb_get_guint8(tvb, offset);
1335
1336     proto_tree_add_item(aal_tree, hf_atm_aa1_csi, tvb, offset, 1, ENC_BIG_ENDIAN);
1337     proto_tree_add_item(aal_tree, hf_atm_aa1_seq_count, tvb, offset, 1, ENC_BIG_ENDIAN);
1338     col_add_fstr(pinfo->cinfo, COL_INFO, "Sequence count = %u",
1339                  (octet >> 4) & 0x7);
1340     proto_tree_add_item(aal_tree, hf_atm_aa1_crc, tvb, offset, 1, ENC_BIG_ENDIAN);
1341     proto_tree_add_item(aal_tree, hf_atm_aa1_parity, tvb, offset, 1, ENC_BIG_ENDIAN);
1342     offset++;
1343
1344     proto_tree_add_item(aal_tree, hf_atm_aa1_payload, tvb, offset, 47, ENC_NA);
1345     break;
1346
1347   case AAL_3_4:
1348     /*
1349      * XXX - or should this be the CS PDU?
1350      */
1351     col_set_str(pinfo->cinfo, COL_PROTOCOL, "AAL3/4");
1352     col_clear(pinfo->cinfo, COL_INFO);
1353     ti = proto_tree_add_item(tree, proto_aal3_4, tvb, offset, -1, ENC_NA);
1354     aal_tree = proto_item_add_subtree(ti, ett_aal3_4);
1355     aal3_4_hdr = tvb_get_ntohs(tvb, offset);
1356     col_add_fstr(pinfo->cinfo, COL_INFO, "%s, sequence number = %u",
1357                  val_to_str(aal3_4_hdr >> 14, st_vals, "Unknown (%u)"),
1358                  (aal3_4_hdr >> 10) & 0xF);
1359     proto_tree_add_item(aal_tree, hf_atm_aal3_4_seg_type, tvb, offset, 2, ENC_BIG_ENDIAN);
1360     proto_tree_add_item(aal_tree, hf_atm_aal3_4_seq_num, tvb, offset, 2, ENC_BIG_ENDIAN);
1361     proto_tree_add_item(aal_tree, hf_atm_aal3_4_multiplex_id, tvb, offset, 2, ENC_BIG_ENDIAN);
1362
1363     length = tvb_reported_length_remaining(tvb, offset);
1364     crc10 = update_crc10_by_bytes_tvb(0, tvb, offset, length);
1365     offset += 2;
1366
1367     proto_tree_add_item(aal_tree, hf_atm_aal3_4_information, tvb, offset, 44, ENC_NA);
1368     offset += 44;
1369
1370     proto_tree_add_item(aal_tree, hf_atm_aal3_4_length_indicator, tvb, offset, 2, ENC_BIG_ENDIAN);
1371     ti = proto_tree_add_item(aal_tree, hf_atm_aal3_4_crc, tvb, offset, 2, ENC_BIG_ENDIAN);
1372     proto_item_append_text(ti, " (%s)", (crc10 == 0) ? " (correct)" : " (incorrect)");
1373     break;
1374
1375   case AAL_OAMCELL:
1376     if (fill_columns)
1377     {
1378       col_set_str(pinfo->cinfo, COL_PROTOCOL, "OAM AAL");
1379       col_clear(pinfo->cinfo, COL_INFO);
1380     }
1381     ti = proto_tree_add_item(tree, proto_oamaal, tvb, offset, -1, ENC_NA);
1382     aal_tree = proto_item_add_subtree(ti, ett_oamaal);
1383     octet = tvb_get_guint8(tvb, offset);
1384     if (fill_columns)
1385     {
1386       col_add_fstr(pinfo->cinfo, COL_INFO, "%s",
1387                    val_to_str(octet >> 4, oam_type_vals, "Unknown (%u)"));
1388     }
1389
1390     proto_tree_add_item(aal_tree, hf_atm_aal_oamcell_type, tvb, offset, 1, ENC_BIG_ENDIAN);
1391     switch (octet >> 4) {
1392
1393     case OAM_TYPE_FM:
1394       proto_tree_add_item(aal_tree, hf_atm_aal_oamcell_type_fm, tvb, offset, 1, ENC_BIG_ENDIAN);
1395       break;
1396
1397     case OAM_TYPE_PM:
1398       proto_tree_add_item(aal_tree, hf_atm_aal_oamcell_type_pm, tvb, offset, 1, ENC_BIG_ENDIAN);
1399       break;
1400
1401     case OAM_TYPE_AD:
1402       proto_tree_add_item(aal_tree, hf_atm_aal_oamcell_type_ad, tvb, offset, 1, ENC_BIG_ENDIAN);
1403       break;
1404
1405     default:
1406       proto_tree_add_item(aal_tree, hf_atm_aal_oamcell_type_ft, tvb, offset, 1, ENC_BIG_ENDIAN);
1407       break;
1408     }
1409     length = tvb_reported_length_remaining(tvb, offset);
1410     crc10 = update_crc10_by_bytes_tvb(0, tvb, offset, length);
1411     offset += 1;
1412
1413     proto_tree_add_item(aal_tree, hf_atm_aal_oamcell_func_spec, tvb, offset, 45, ENC_NA);
1414     offset += 45;
1415
1416     ti = proto_tree_add_item(aal_tree, hf_atm_aal_oamcell_crc, tvb, offset, 2, ENC_BIG_ENDIAN);
1417     proto_item_append_text(ti, " (%s)", (crc10 == 0) ? " (correct)" : " (incorrect)");
1418     break;
1419
1420   default:
1421     next_tvb = tvb_new_subset_remaining(tvb, offset);
1422     call_data_dissector(next_tvb, pinfo, tree);
1423     break;
1424   }
1425 }
1426
1427 /*
1428  * Check for OAM cells.
1429  * OAM F4 is VCI 3 or 4 and PT 0X0.
1430  * OAM F5 is PT 10X.
1431  */
1432 gboolean
1433 atm_is_oam_cell(const guint16 vci, const guint8 pt)
1434 {
1435   return  (((vci == 3 || vci == 4) && ((pt & 0x5) == 0))
1436            || ((pt & 0x6) == 0x4));
1437 }
1438
1439
1440 static void
1441 dissect_atm_cell(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1442                  proto_tree *atm_tree, guint aal, gboolean nni,
1443                  gboolean crc_stripped)
1444 {
1445   int         offset;
1446   proto_item *ti;
1447   guint8      octet, pt;
1448   int         err;
1449   guint16     vpi, vci;
1450
1451   if (!nni) {
1452     /*
1453      * FF: ITU-T I.361 (Section 2.2) defines the cell header format
1454      * and encoding at UNI reference point as:
1455      *
1456      *  8 7 6 5 4 3 2 1
1457      * +-+-+-+-+-+-+-+-+
1458      * |  GFC  |  VPI  |
1459      * +-+-+-+-+-+-+-+-+
1460      * |  VPI  |  VCI  |
1461      * +-+-+-+-+-+-+-+-+
1462      * |      VCI      |
1463      * +-+-+-+-+-+-+-+-+
1464      * |  VCI  |  PT |C|
1465      * +-+-+-+-+-+-+-+-+
1466      * |   HEC (CRC)   |
1467      * +-+-+-+-+-+-+-+-+
1468      */
1469     octet = tvb_get_guint8(tvb, 0);
1470     proto_tree_add_item(atm_tree, hf_atm_gfc, tvb, 0, 1, ENC_NA);
1471     vpi = (octet & 0xF) << 4;
1472     octet = tvb_get_guint8(tvb, 1);
1473     vpi |= octet >> 4;
1474     proto_tree_add_uint(atm_tree, hf_atm_vpi, tvb, 0, 2, vpi);
1475   } else {
1476     /*
1477      * FF: ITU-T I.361 (Section 2.3) defines the cell header format
1478      * and encoding at NNI reference point as:
1479      *
1480      *  8 7 6 5 4 3 2 1
1481      * +-+-+-+-+-+-+-+-+
1482      * |      VPI      |
1483      * +-+-+-+-+-+-+-+-+
1484      * |  VPI  |  VCI  |
1485      * +-+-+-+-+-+-+-+-+
1486      * |      VCI      |
1487      * +-+-+-+-+-+-+-+-+
1488      * |  VCI  |  PT |C|
1489      * +-+-+-+-+-+-+-+-+
1490      * |   HEC (CRC)   |
1491      * +-+-+-+-+-+-+-+-+
1492      */
1493     octet = tvb_get_guint8(tvb, 0);
1494     vpi = octet << 4;
1495     octet = tvb_get_guint8(tvb, 1);
1496     vpi |= (octet & 0xF0) >> 4;
1497     proto_tree_add_uint(atm_tree, hf_atm_vpi, tvb, 0, 2, vpi);
1498   }
1499
1500   vci = (octet & 0x0F) << 12;
1501   octet = tvb_get_guint8(tvb, 2);
1502   vci |= octet << 4;
1503   octet = tvb_get_guint8(tvb, 3);
1504   vci |= octet >> 4;
1505   proto_tree_add_uint(atm_tree, hf_atm_vci, tvb, 1, 3, vci);
1506   pt = (octet >> 1) & 0x7;
1507   proto_tree_add_item(atm_tree, hf_atm_payload_type, tvb, 3, 1, ENC_BIG_ENDIAN);
1508   proto_tree_add_item(atm_tree, hf_atm_cell_loss_priority, tvb, 3, 1, ENC_BIG_ENDIAN);
1509
1510   if (!crc_stripped) {
1511     /*
1512      * FF: parse the Header Error Check (HEC).
1513      */
1514     ti = proto_tree_add_item(atm_tree, hf_atm_header_error_check, tvb, 4, 1, ENC_BIG_ENDIAN);
1515     err = get_header_err((const guint8*)tvb_memdup(wmem_packet_scope(), tvb, 0, 5));
1516     if (err == NO_ERROR_DETECTED)
1517       proto_item_append_text(ti, " (correct)");
1518     else if (err == UNCORRECTIBLE_ERROR)
1519       proto_item_append_text(ti, " (uncorrectable error)");
1520     else
1521       proto_item_append_text(ti, " (error in bit %d)", err);
1522     offset = 5;
1523   } else {
1524     /*
1525      * FF: in some encapsulation modes (e.g. RFC 4717, ATM N-to-One
1526      * Cell Mode) the Header Error Check (HEC) field is stripped.
1527      * So we do nothing here.
1528      */
1529     offset = 4;
1530   }
1531
1532   /*
1533    * Check for OAM cells.
1534    * XXX - do this for all AAL values, overriding whatever information
1535    * Wiretap got from the file?
1536    */
1537   if (aal == AAL_USER || aal == AAL_UNKNOWN) {
1538     if (atm_is_oam_cell(vci,pt)) {
1539       aal = AAL_OAMCELL;
1540     }
1541   }
1542
1543   dissect_atm_cell_payload(tvb, offset, pinfo, tree, aal, TRUE);
1544 }
1545
1546 static int
1547 dissect_atm_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1548     gboolean truncated, struct atm_phdr *atm_info, gboolean pseudowire_mode)
1549 {
1550   proto_tree *atm_tree        = NULL;
1551   proto_item *atm_ti          = NULL;
1552
1553   if ( atm_info->aal == AAL_5 && atm_info->type == TRAF_LANE &&
1554        dissect_lanesscop ) {
1555     atm_info->aal = AAL_SIGNALLING;
1556   }
1557
1558   col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATM");
1559
1560   if (!pseudowire_mode) {
1561     switch (atm_info->channel) {
1562
1563     case 0:
1564       /* Traffic from DTE to DCE. */
1565       col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DCE");
1566       col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DTE");
1567       break;
1568
1569     case 1:
1570       /* Traffic from DCE to DTE. */
1571       col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DTE");
1572       col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DCE");
1573       break;
1574     }
1575   }
1576
1577   if (atm_info->aal == AAL_5) {
1578     col_add_fstr(pinfo->cinfo, COL_INFO, "AAL5 %s",
1579                  val_to_str(atm_info->type, aal5_hltype_vals,
1580                             "Unknown traffic type (%u)"));
1581   } else {
1582     col_add_str(pinfo->cinfo, COL_INFO,
1583                 val_to_str(atm_info->aal, aal_vals,
1584                            "Unknown AAL (%u)"));
1585   }
1586
1587   if (tree) {
1588     atm_ti = proto_tree_add_item(tree, proto_atm, tvb, 0, -1, ENC_NA);
1589     atm_tree = proto_item_add_subtree(atm_ti, ett_atm);
1590
1591     if (!pseudowire_mode) {
1592       proto_tree_add_uint(atm_tree, hf_atm_channel, tvb, 0, 0, atm_info->channel);
1593       if (atm_info->flags & ATM_REASSEMBLY_ERROR)
1594         expert_add_info(pinfo, atm_ti, &ei_atm_reassembly_failed);
1595     }
1596
1597     proto_tree_add_uint_format_value(atm_tree, hf_atm_aal, tvb, 0, 0,
1598                                      atm_info->aal,
1599                                      "%s",
1600                                      val_to_str(atm_info->aal, aal_vals,
1601                                                 "Unknown AAL (%u)"));
1602   }
1603   if (atm_info->flags & ATM_RAW_CELL) {
1604     /* This is a single cell, with the cell header at the beginning. */
1605     if (atm_info->flags & ATM_NO_HEC) {
1606       proto_item_set_len(atm_ti, 4);
1607     } else {
1608       proto_item_set_len(atm_ti, 5);
1609     }
1610     dissect_atm_cell(tvb, pinfo, tree, atm_tree,
1611                      atm_info->aal, FALSE,
1612                      atm_info->flags & ATM_NO_HEC);
1613   } else {
1614     /* This is a reassembled PDU. */
1615
1616     /*
1617      * ATM dissector is used as "sub-dissector" for ATM pseudowires.
1618      * In such cases, the dissector data parameter is used to pass info from/to
1619      * PW dissector to ATM dissector. For decoding normal ATM traffic
1620      * data parameter should be NULL.
1621      */
1622     dissect_reassembled_pdu(tvb, pinfo, tree, atm_tree, atm_ti, truncated,
1623                             atm_info, pseudowire_mode);
1624   }
1625
1626   return tvb_reported_length(tvb);
1627 }
1628
1629 static int
1630 dissect_atm_truncated(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
1631 {
1632   struct atm_phdr *atm_info = (struct atm_phdr *)data;
1633
1634   DISSECTOR_ASSERT(atm_info != NULL);
1635
1636   return dissect_atm_common(tvb, pinfo, tree, TRUE, atm_info, FALSE);
1637 }
1638
1639 static int
1640 dissect_atm_pw_truncated(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
1641 {
1642   struct atm_phdr *atm_info = (struct atm_phdr *)data;
1643
1644   DISSECTOR_ASSERT(atm_info != NULL);
1645
1646   return dissect_atm_common(tvb, pinfo, tree, TRUE, atm_info, TRUE);
1647 }
1648
1649 static int
1650 dissect_atm_untruncated(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
1651 {
1652   struct atm_phdr *atm_info = (struct atm_phdr *)data;
1653
1654   DISSECTOR_ASSERT(atm_info != NULL);
1655
1656   return dissect_atm_common(tvb, pinfo, tree, FALSE, atm_info, FALSE);
1657 }
1658
1659 static int
1660 dissect_atm_pw_untruncated(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
1661 {
1662   struct atm_phdr *atm_info = (struct atm_phdr *)data;
1663
1664   DISSECTOR_ASSERT(atm_info != NULL);
1665
1666   return dissect_atm_common(tvb, pinfo, tree, FALSE, atm_info, TRUE);
1667 }
1668
1669 static int
1670 dissect_atm_oam_cell(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
1671 {
1672   proto_tree *atm_tree;
1673   proto_item *atm_ti;
1674
1675   col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATM");
1676
1677   atm_ti   = proto_tree_add_item(tree, proto_atm, tvb, 0, 0, ENC_NA);
1678   atm_tree = proto_item_add_subtree(atm_ti, ett_atm);
1679
1680   dissect_atm_cell(tvb, pinfo, tree, atm_tree, AAL_OAMCELL, FALSE, FALSE);
1681   return tvb_reported_length(tvb);
1682 }
1683
1684 static int
1685 dissect_atm_pw_oam_cell(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
1686 {
1687   const pwatm_private_data_t *pwpd = (const pwatm_private_data_t *)data;
1688
1689   col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATM");
1690
1691   dissect_atm_cell_payload(tvb, 0, pinfo, tree, AAL_OAMCELL,
1692                            pwpd->enable_fill_columns_by_atm_dissector);
1693
1694   return tvb_reported_length(tvb);
1695 }
1696
1697 static void atm_prompt(packet_info *pinfo _U_, gchar* result)
1698 {
1699   g_snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "Decode AAL2 traffic as");
1700 }
1701
1702 static gpointer atm_value(packet_info *pinfo)
1703 {
1704   return GUINT_TO_POINTER((guint)pinfo->pseudo_header->atm.type);
1705 }
1706
1707 void
1708 proto_register_atm(void)
1709 {
1710   static hf_register_info hf[] = {
1711     { &hf_atm_aal,
1712       { "AAL",          "atm.aal", FT_UINT8, BASE_DEC, VALS(aal_vals), 0x0,
1713         NULL, HFILL }},
1714     { &hf_atm_gfc,
1715       { "GFC",          "atm.GFC", FT_UINT8, BASE_DEC, NULL, 0xF0,
1716         NULL, HFILL }},
1717     { &hf_atm_vpi,
1718       { "VPI",          "atm.vpi", FT_UINT8, BASE_DEC, NULL, 0x0,
1719         NULL, HFILL }},
1720
1721     { &hf_atm_vci,
1722       { "VCI",          "atm.vci", FT_UINT16, BASE_DEC, NULL, 0x0,
1723         NULL, HFILL }},
1724
1725     { &hf_atm_cid,
1726       { "CID",          "atm.cid", FT_UINT8, BASE_DEC, NULL, 0x0,
1727         NULL, HFILL }},
1728
1729     { &hf_atm_reserved,
1730       { "Reserved", "atm.reserved", FT_BYTES, BASE_NONE, NULL, 0x0,
1731         NULL, HFILL }},
1732
1733     { &hf_atm_le_client_client,
1734       { "LE Client", "atm.le_client.client", FT_UINT16, BASE_HEX, NULL, 0x0,
1735         NULL, HFILL }},
1736     { &hf_atm_lan_destination_tag,
1737       { "Tag", "atm.lan_destination.tag", FT_UINT16, BASE_HEX, VALS(le_control_landest_tag_vals), 0x0,
1738         NULL, HFILL }},
1739     { &hf_atm_lan_destination_mac,
1740       { "MAC address", "atm.lan_destination.mac", FT_ETHER, BASE_NONE, NULL, 0x0,
1741         NULL, HFILL }},
1742     { &hf_atm_le_control_tlv_type,
1743       { "TLV Type", "atm.le_control.tlv_type", FT_UINT32, BASE_HEX, VALS(le_tlv_type_vals), 0x0,
1744         NULL, HFILL }},
1745     { &hf_atm_le_control_tlv_length,
1746       { "TLV Length", "atm.le_control.tlv_length", FT_UINT8, BASE_DEC, NULL, 0x0,
1747         NULL, HFILL }},
1748     { &hf_atm_lan_destination_route_desc,
1749       { "Route descriptor", "atm.lan_destination.route_desc", FT_UINT16, BASE_HEX, NULL, 0x0,
1750         NULL, HFILL }},
1751     { &hf_atm_lan_destination_lan_id,
1752       { "LAN ID", "atm.lan_destination.lan_id", FT_UINT16, BASE_DEC, NULL, 0xFFF0,
1753         NULL, HFILL }},
1754     { &hf_atm_lan_destination_bridge_num,
1755       { "Bridge number", "atm.lan_destination.bridge_num", FT_UINT16, BASE_DEC, NULL, 0x000F,
1756         NULL, HFILL }},
1757     { &hf_atm_source_atm,
1758       { "Source ATM address", "atm.source_atm", FT_BYTES, BASE_NONE, NULL, 0x0,
1759         NULL, HFILL }},
1760     { &hf_atm_target_atm,
1761       { "Target ATM address", "atm.target_atm", FT_BYTES, BASE_NONE, NULL, 0x0,
1762         NULL, HFILL }},
1763     { &hf_atm_le_configure_join_frame_lan_type,
1764       { "LAN type", "atm.le_configure_join_frame.lan_type", FT_UINT8, BASE_HEX, VALS(le_control_lan_type_vals), 0x0,
1765         NULL, HFILL }},
1766     { &hf_atm_le_configure_join_frame_max_frame_size,
1767       { "Maximum frame size", "atm.le_configure_join_frame.max_frame_size", FT_UINT8, BASE_HEX, VALS(le_control_frame_size_vals), 0x0,
1768         NULL, HFILL }},
1769     { &hf_atm_le_configure_join_frame_num_tlvs,
1770       { "Number of TLVs", "atm.le_configure_join_frame.num_tlvs", FT_UINT8, BASE_DEC, NULL, 0x0,
1771         NULL, HFILL }},
1772     { &hf_atm_le_configure_join_frame_elan_name_size,
1773       { "ELAN name size", "atm.le_configure_join_frame.elan_name_size", FT_UINT8, BASE_DEC, NULL, 0x0,
1774         NULL, HFILL }},
1775     { &hf_atm_le_registration_frame_num_tlvs,
1776       { "Number of TLVs", "atm.le_registration_frame.num_tlvs", FT_UINT8, BASE_DEC, NULL, 0x0,
1777         NULL, HFILL }},
1778     { &hf_atm_le_arp_frame_num_tlvs,
1779       { "Number of TLVs", "atm.le_arp_frame.num_tlvs", FT_UINT8, BASE_DEC, NULL, 0x0,
1780         NULL, HFILL }},
1781     { &hf_atm_le_verify_frame_num_tlvs,
1782       { "Number of TLVs", "atm.le_verify_frame.num_tlvs", FT_UINT8, BASE_DEC, NULL, 0x0,
1783         NULL, HFILL }},
1784     { &hf_atm_le_configure_join_frame_elan_name,
1785       { "ELAN name", "atm.le_configure_join_frame.elan_name", FT_BYTES, BASE_NONE, NULL, 0x0,
1786         NULL, HFILL }},
1787     { &hf_atm_le_control_marker,
1788       { "Marker", "atm.le_control.marker", FT_UINT16, BASE_HEX, NULL, 0x0,
1789         NULL, HFILL }},
1790     { &hf_atm_le_control_protocol,
1791       { "Protocol", "atm.le_control.protocol", FT_UINT8, BASE_HEX, NULL, 0x0,
1792         NULL, HFILL }},
1793     { &hf_atm_le_control_version,
1794       { "Version", "atm.le_control.version", FT_UINT8, BASE_HEX, NULL, 0x0,
1795         NULL, HFILL }},
1796     { &hf_atm_le_control_opcode,
1797       { "Opcode", "atm.le_control.opcode", FT_UINT16, BASE_HEX, VALS(le_control_opcode_vals), 0x0,
1798         NULL, HFILL }},
1799     { &hf_atm_le_control_status,
1800       { "Status", "atm.le_control.status", FT_UINT16, BASE_HEX, VALS(le_control_status_vals), 0x0,
1801         NULL, HFILL }},
1802     { &hf_atm_le_control_transaction_id,
1803       { "Transaction ID", "atm.le_control.transaction_id", FT_UINT32, BASE_HEX, NULL, 0x0,
1804         NULL, HFILL }},
1805     { &hf_atm_le_control_requester_lecid,
1806       { "Requester LECID", "atm.le_control.requester_lecid", FT_UINT16, BASE_HEX, NULL, 0x0,
1807         NULL, HFILL }},
1808     { &hf_atm_le_control_flags,
1809       { "Flags", "atm.le_control.flag", FT_UINT16, BASE_HEX, NULL, 0x0,
1810         NULL, HFILL }},
1811     { &hf_atm_le_control_flag_v2_capable,
1812       { "V2 capable", "atm.le_control.flag.v2_capable", FT_BOOLEAN, 16, TFS(&tfs_yes_no), 0x0002,
1813         NULL, HFILL }},
1814     { &hf_atm_le_control_flag_selective_multicast,
1815       { "Selective multicast", "atm.le_control.flag.selective_multicast", FT_BOOLEAN, 16, TFS(&tfs_yes_no), 0x0004,
1816         NULL, HFILL }},
1817     { &hf_atm_le_control_flag_v2_required,
1818       { "V2 required", "atm.le_control.flag.v2_required", FT_BOOLEAN, 16, TFS(&tfs_yes_no), 0x0008,
1819         NULL, HFILL }},
1820     { &hf_atm_le_control_flag_proxy,
1821       { "Proxy", "atm.le_control.flag.flag_proxy", FT_BOOLEAN, 16, TFS(&tfs_yes_no), 0x0080,
1822         NULL, HFILL }},
1823     { &hf_atm_le_control_flag_exclude_explorer_frames,
1824       { "Exclude explorer frames", "atm.le_control.flag.exclude_explorer_frames", FT_BOOLEAN, 16, TFS(&tfs_yes_no), 0x0200,
1825         NULL, HFILL }},
1826     { &hf_atm_le_control_flag_address,
1827       { "Address", "atm.le_control.flag.address", FT_BOOLEAN, 16, TFS(&tfs_yes_no), 0x0001,
1828         NULL, HFILL }},
1829     { &hf_atm_le_control_topology_change,
1830       { "Topology change", "atm.le_control.flag.topology_change", FT_BOOLEAN, 16, TFS(&tfs_remote_local), 0x0100,
1831         NULL, HFILL }},
1832     { &hf_atm_traffic_type,
1833       { "Traffic type", "atm.traffic_type", FT_UINT8, BASE_DEC, VALS(aal5_hltype_vals), 0x0,
1834         NULL, HFILL }},
1835     { &hf_atm_traffic_vcmx,
1836       { "VC multiplexed traffic type", "atm.traffic.vcmx", FT_UINT8, BASE_DEC, VALS(vcmx_type_vals), 0x0,
1837         NULL, HFILL }},
1838     { &hf_atm_traffic_lane,
1839       { "LANE traffic type", "atm.traffic.lane", FT_UINT8, BASE_DEC, VALS(lane_type_vals), 0x0,
1840         NULL, HFILL }},
1841     { &hf_atm_traffic_ipsilon,
1842       { "Ipsilon traffic type", "atm.traffic.ipsilon", FT_UINT8, BASE_DEC, VALS(ipsilon_type_vals), 0x0,
1843         NULL, HFILL }},
1844     { &hf_atm_cells,
1845       { "Cells", "atm.cells", FT_UINT16, BASE_DEC, NULL, 0x0,
1846         NULL, HFILL }},
1847     { &hf_atm_aal5_uu,
1848       { "AAL5 UU", "atm.hf_atm.aal5t_uu", FT_UINT8, BASE_HEX, NULL, 0x0,
1849         NULL, HFILL }},
1850     { &hf_atm_aal5_cpi,
1851       { "AAL5 CPI", "atm.hf_atm.aal5t_cpi", FT_UINT8, BASE_HEX, NULL, 0x0,
1852         NULL, HFILL }},
1853     { &hf_atm_aal5_len,
1854       { "AAL5 len", "atm.aal5t_len", FT_UINT16, BASE_DEC, NULL, 0x0,
1855         NULL, HFILL }},
1856     { &hf_atm_aal5_crc,
1857       { "AAL5 CRC", "atm.aal5t_crc", FT_UINT32, BASE_HEX, NULL, 0x0,
1858         NULL, HFILL }},
1859     { &hf_atm_payload_type,
1860       { "Payload Type", "atm.payload_type", FT_UINT8, BASE_DEC, NULL, 0x0E,
1861         NULL, HFILL }},
1862     { &hf_atm_cell_loss_priority,
1863       { "Cell Loss Priority", "atm.cell_loss_priority", FT_BOOLEAN, 8, TFS(&tfs_low_high_priority), 0x01,
1864         NULL, HFILL }},
1865     { &hf_atm_header_error_check,
1866       { "Header Error Check", "atm.header_error_check", FT_UINT8, BASE_HEX, NULL, 0,
1867         NULL, HFILL }},
1868     { &hf_atm_channel,
1869       { "Channel", "atm.channel", FT_UINT16, BASE_DEC, VALS(atm_channel_vals), 0,
1870         NULL, HFILL }},
1871     { &hf_atm_aa1_csi,
1872       { "CSI", "atm.aa1.csi", FT_UINT8, BASE_DEC, NULL, 0x80,
1873         NULL, HFILL }},
1874     { &hf_atm_aa1_seq_count,
1875       { "Sequence Count", "atm.aa1.seq_count", FT_UINT8, BASE_DEC, NULL, 0x70,
1876         NULL, HFILL }},
1877     { &hf_atm_aa1_crc,
1878       { "CRC", "atm.aa1.crc", FT_UINT8, BASE_DEC, NULL, 0x08,
1879         NULL, HFILL }},
1880     { &hf_atm_aa1_parity,
1881       { "Parity", "atm.aa1.parity", FT_UINT8, BASE_DEC, NULL, 0x07,
1882         NULL, HFILL }},
1883     { &hf_atm_aa1_payload,
1884       { "Payload", "atm.aa1.payload", FT_BYTES, BASE_NONE, NULL, 0x0,
1885         NULL, HFILL }},
1886     { &hf_atm_aal3_4_seg_type,
1887       { "Segment Type", "atm.aal3_4.seg_type", FT_UINT16, BASE_DEC, VALS(st_vals), 0xC000,
1888         NULL, HFILL }},
1889     { &hf_atm_aal3_4_seq_num,
1890       { "Sequence Number", "atm.aal3_4.seq_num", FT_UINT16, BASE_DEC, NULL, 0x3C00,
1891         NULL, HFILL }},
1892     { &hf_atm_aal3_4_multiplex_id,
1893       { "Multiplex ID", "atm.aal3_4.multiplex_id", FT_UINT16, BASE_DEC, NULL, 0x03FF,
1894         NULL, HFILL }},
1895     { &hf_atm_aal3_4_information,
1896       { "Information", "atm.aal3_4.information", FT_BYTES, BASE_NONE, NULL, 0x0,
1897         NULL, HFILL }},
1898     { &hf_atm_aal3_4_length_indicator,
1899       { "Length Indicator", "atm.aal3_4.length_indicator", FT_UINT16, BASE_DEC, VALS(st_vals), 0xFC00,
1900         NULL, HFILL }},
1901     { &hf_atm_aal3_4_crc,
1902       { "CRC", "atm.aal3_4.crc", FT_UINT16, BASE_DEC, NULL, 0x03FF,
1903         NULL, HFILL }},
1904     { &hf_atm_aal_oamcell_type,
1905       { "OAM Type", "atm.aal_oamcell.type", FT_UINT8, BASE_DEC, VALS(oam_type_vals), 0xF0,
1906         NULL, HFILL }},
1907     { &hf_atm_aal_oamcell_type_fm,
1908       { "Function Type", "atm.aal_oamcell.type.fm", FT_UINT8, BASE_DEC, VALS(ft_fm_vals), 0x0F,
1909         NULL, HFILL }},
1910     { &hf_atm_aal_oamcell_type_pm,
1911       { "Function Type", "atm.aal_oamcell.type.pm", FT_UINT8, BASE_DEC, VALS(ft_pm_vals), 0x0F,
1912         NULL, HFILL }},
1913     { &hf_atm_aal_oamcell_type_ad,
1914       { "Function Type", "atm.aal_oamcell.type.ad", FT_UINT8, BASE_DEC, VALS(ft_ad_vals), 0x0F,
1915         NULL, HFILL }},
1916     { &hf_atm_aal_oamcell_type_ft,
1917       { "Function Type", "atm.aal_oamcell.type.ft", FT_UINT8, BASE_DEC, NULL, 0x0F,
1918         NULL, HFILL }},
1919     { &hf_atm_aal_oamcell_func_spec,
1920       { "Function-specific information", "atm.aal_oamcell.func_spec", FT_BYTES, BASE_NONE, NULL, 0x0,
1921         NULL, HFILL }},
1922     { &hf_atm_aal_oamcell_crc,
1923       { "CRC-10", "atm.aal_oamcell.crc", FT_UINT16, BASE_HEX, NULL, 0x3FF,
1924         NULL, HFILL }},
1925     { &hf_atm_padding,
1926       { "Padding", "atm.padding", FT_BYTES, BASE_NONE, NULL, 0x0,
1927         NULL, HFILL }},
1928
1929   };
1930
1931   static gint *ett[] = {
1932     &ett_atm,
1933     &ett_ilmi,
1934     &ett_aal1,
1935     &ett_aal3_4,
1936     &ett_oamaal,
1937     &ett_atm_lane,
1938     &ett_atm_lane_lc_lan_dest,
1939     &ett_atm_lane_lc_lan_dest_rd,
1940     &ett_atm_lane_lc_flags,
1941     &ett_atm_lane_lc_tlv,
1942   };
1943
1944   static ei_register_info ei[] = {
1945     { &ei_atm_reassembly_failed, { "atm.reassembly_failed", PI_REASSEMBLE, PI_ERROR, "PDU reassembly failed", EXPFILL }},
1946   };
1947
1948   expert_module_t* expert_atm;
1949   module_t *atm_module;
1950
1951   /* Decode As handling */
1952   static build_valid_func atm_da_build_value[1] = {atm_value};
1953   static decode_as_value_t atm_da_values = {atm_prompt, 1, atm_da_build_value};
1954   static decode_as_t atm_da = {"atm", "Network", "atm.aal2.type", 1, 0, &atm_da_values, NULL, NULL,
1955                                 decode_as_default_populate_list, decode_as_default_reset, decode_as_default_change, NULL};
1956
1957   proto_atm    = proto_register_protocol("Asynchronous Transfer Mode", "ATM", "atm");
1958   proto_aal1   = proto_register_protocol("ATM AAL1", "AAL1", "aal1");
1959   proto_aal3_4 = proto_register_protocol("ATM AAL3/4", "AAL3/4", "aal3_4");
1960   proto_oamaal = proto_register_protocol("ATM OAM AAL", "OAM AAL", "oamaal");
1961   proto_register_field_array(proto_atm, hf, array_length(hf));
1962   proto_register_subtree_array(ett, array_length(ett));
1963   expert_atm = expert_register_protocol(proto_atm);
1964   expert_register_field_array(expert_atm, ei, array_length(ei));
1965
1966   proto_ilmi = proto_register_protocol("ILMI", "ILMI", "ilmi");
1967
1968   proto_atm_lane = proto_register_protocol("ATM LAN Emulation", "ATM LANE", "lane");
1969
1970   atm_type_aal2_table = register_dissector_table("atm.aal2.type", "ATM AAL_2 type", proto_atm, FT_UINT32, BASE_DEC);
1971   atm_type_aal5_table = register_dissector_table("atm.aal5.type", "ATM AAL_5 type", proto_atm, FT_UINT32, BASE_DEC);
1972
1973   register_capture_dissector_table("atm.aal5.type", "ATM AAL_5");
1974   register_capture_dissector_table("atm_lane", "ATM LAN Emulation");
1975
1976   atm_handle = register_dissector("atm_truncated", dissect_atm_truncated, proto_atm);
1977   register_dissector("atm_pw_truncated", dissect_atm_pw_truncated, proto_atm);
1978   atm_untruncated_handle = register_dissector("atm_untruncated", dissect_atm_untruncated, proto_atm);
1979   register_dissector("atm_pw_untruncated", dissect_atm_pw_untruncated, proto_atm);
1980   register_dissector("atm_oam_cell", dissect_atm_oam_cell, proto_oamaal);
1981   register_dissector("atm_pw_oam_cell", dissect_atm_pw_oam_cell, proto_oamaal);
1982
1983   atm_module = prefs_register_protocol ( proto_atm, NULL );
1984   prefs_register_bool_preference(atm_module, "dissect_lane_as_sscop", "Dissect LANE as SSCOP",
1985                                  "Autodection between LANE and SSCOP is hard. As default LANE is preferred",
1986                                  &dissect_lanesscop);
1987   prefs_register_obsolete_preference(atm_module, "unknown_aal2_type");
1988
1989   register_decode_as(&atm_da);
1990 }
1991
1992 void
1993 proto_reg_handoff_atm(void)
1994 {
1995   capture_dissector_handle_t atm_cap_handle;
1996
1997   /*
1998    * Get handles for the Ethernet, Token Ring, Frame Relay, LLC,
1999    * SSCOP, LANE, and ILMI dissectors.
2000    */
2001   eth_withoutfcs_handle = find_dissector_add_dependency("eth_withoutfcs", proto_atm_lane);
2002   tr_handle             = find_dissector_add_dependency("tr", proto_atm_lane);
2003   fr_handle             = find_dissector_add_dependency("fr", proto_atm);
2004   llc_handle            = find_dissector_add_dependency("llc", proto_atm);
2005   sscop_handle          = find_dissector_add_dependency("sscop", proto_atm);
2006   ppp_handle            = find_dissector_add_dependency("ppp", proto_atm);
2007   eth_maybefcs_handle   = find_dissector_add_dependency("eth_maybefcs", proto_atm);
2008   ip_handle             = find_dissector_add_dependency("ip", proto_atm);
2009
2010   dissector_add_uint("wtap_encap", WTAP_ENCAP_ATM_PDUS, atm_handle);
2011   dissector_add_uint("atm.aal5.type", TRAF_LANE, create_dissector_handle(dissect_lane, proto_atm_lane));
2012   dissector_add_uint("atm.aal5.type", TRAF_ILMI, create_dissector_handle(dissect_ilmi, proto_ilmi));
2013
2014   dissector_add_uint("wtap_encap", WTAP_ENCAP_ATM_PDUS_UNTRUNCATED,
2015                 atm_untruncated_handle);
2016
2017   atm_cap_handle = create_capture_dissector_handle(capture_atm, proto_atm);
2018   capture_dissector_add_uint("wtap_encap", WTAP_ENCAP_ATM_PDUS, atm_cap_handle);
2019   atm_cap_handle = create_capture_dissector_handle(capture_lane, proto_atm_lane);
2020   capture_dissector_add_uint("atm.aal5.type", TRAF_LANE, atm_cap_handle);
2021 }
2022
2023 /*
2024  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
2025  *
2026  * Local Variables:
2027  * c-basic-offset: 2
2028  * tab-width: 8
2029  * indent-tabs-mode: nil
2030  * End:
2031  *
2032  * ex: set shiftwidth=2 tabstop=8 expandtab:
2033  * :indentSize=2:tabSize=8:noTabs=true:
2034  */