For proto_tree_add_item(..., proto_xxx, ...)use ENC_NA as the encoding arg.
[obnox/wireshark/wip.git] / epan / dissectors / packet-atm.c
1 /* packet-atm.c
2  * Routines for ATM packet disassembly
3  *
4  * $Id$
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #include <glib.h>
30 #include <epan/packet.h>
31 #include <epan/oui.h>
32 #include <epan/addr_resolv.h>
33 #include <epan/ppptypes.h>
34
35 #include "packet-atm.h"
36 #include "packet-snmp.h"
37 #include "packet-eth.h"
38 #include "packet-tr.h"
39 #include "packet-llc.h"
40 #include <epan/prefs.h>
41 #include "packet-pw-atm.h"
42
43 static int proto_atm = -1;
44 static int hf_atm_aal = -1;
45 static int hf_atm_vpi = -1;
46 static int hf_atm_vci = -1;
47 static int hf_atm_cid = -1;
48 static int proto_atm_lane = -1;
49 static int proto_ilmi = -1;
50 static int proto_aal1 = -1;
51 static int proto_aal3_4 = -1;
52 static int proto_oamaal = -1;
53
54 static gint ett_atm = -1;
55 static gint ett_atm_lane = -1;
56 static gint ett_atm_lane_lc_lan_dest = -1;
57 static gint ett_atm_lane_lc_lan_dest_rd = -1;
58 static gint ett_atm_lane_lc_flags = -1;
59 static gint ett_atm_lane_lc_tlv = -1;
60 static gint ett_ilmi = -1;
61 static gint ett_aal1 = -1;
62 static gint ett_aal3_4 = -1;
63 static gint ett_oamaal = -1;
64
65 static dissector_handle_t eth_withoutfcs_handle;
66 static dissector_handle_t tr_handle;
67 static dissector_handle_t fr_handle;
68 static dissector_handle_t llc_handle;
69 static dissector_handle_t sscop_handle;
70 static dissector_handle_t lane_handle;
71 static dissector_handle_t ilmi_handle;
72 static dissector_handle_t fp_handle;
73 static dissector_handle_t ppp_handle;
74 static dissector_handle_t eth_handle;
75 static dissector_handle_t ip_handle;
76 static dissector_handle_t data_handle;
77 static dissector_handle_t gprs_ns_handle;
78
79 static gboolean dissect_lanesscop = FALSE;
80
81 static gint unknown_aal2_type = TRAF_UNKNOWN;
82
83 /*
84  * See
85  *
86  *      http://www.atmforum.org/atmforum/specs/approved.html
87  *
88  * for a number of ATM Forum specifications, e.g. the LAN Emulation
89  * over ATM 1.0 spec, whence I got most of this.
90  */
91
92 /* LE Control opcodes */
93 #define LE_CONFIGURE_REQUEST    0x0001
94 #define LE_CONFIGURE_RESPONSE   0x0101
95 #define LE_JOIN_REQUEST         0x0002
96 #define LE_JOIN_RESPONSE        0x0102
97 #define READY_QUERY             0x0003
98 #define READY_IND               0x0103
99 #define LE_REGISTER_REQUEST     0x0004
100 #define LE_REGISTER_RESPONSE    0x0104
101 #define LE_UNREGISTER_REQUEST   0x0005
102 #define LE_UNREGISTER_RESPONSE  0x0105
103 #define LE_ARP_REQUEST          0x0006
104 #define LE_ARP_RESPONSE         0x0106
105 #define LE_FLUSH_REQUEST        0x0007
106 #define LE_FLUSH_RESPONSE       0x0107
107 #define LE_NARP_REQUEST         0x0008
108 #define LE_TOPOLOGY_REQUEST     0x0009
109 #define LE_VERIFY_REQUEST       0x000A
110 #define LE_VERIFY_RESPONSE      0x010A
111
112 static const value_string le_control_opcode_vals[] = {
113   { LE_CONFIGURE_REQUEST,   "LE_CONFIGURE_REQUEST" },
114   { LE_CONFIGURE_RESPONSE,  "LE_CONFIGURE_RESPONSE" },
115   { LE_JOIN_REQUEST,        "LE_JOIN_REQUEST" },
116   { LE_JOIN_RESPONSE,       "LE_JOIN_RESPONSE" },
117   { READY_QUERY,            "READY_QUERY" },
118   { READY_IND,              "READY_IND" },
119   { LE_REGISTER_REQUEST,    "LE_REGISTER_REQUEST" },
120   { LE_REGISTER_RESPONSE,   "LE_REGISTER_RESPONSE" },
121   { LE_UNREGISTER_REQUEST,  "LE_UNREGISTER_REQUEST" },
122   { LE_UNREGISTER_RESPONSE, "LE_UNREGISTER_RESPONSE" },
123   { LE_ARP_REQUEST,         "LE_ARP_REQUEST" },
124   { LE_ARP_RESPONSE,        "LE_ARP_RESPONSE" },
125   { LE_FLUSH_REQUEST,       "LE_FLUSH_REQUEST" },
126   { LE_FLUSH_RESPONSE,      "LE_FLUSH_RESPONSE" },
127   { LE_NARP_REQUEST,        "LE_NARP_REQUEST" },
128   { LE_TOPOLOGY_REQUEST,    "LE_TOPOLOGY_REQUEST" },
129   { LE_VERIFY_REQUEST,      "LE_VERIFY_REQUEST" },
130   { LE_VERIFY_RESPONSE,     "LE_VERIFY_RESPONSE" },
131   { 0,                      NULL }
132 };
133
134 /* LE Control statuses */
135 static const value_string le_control_status_vals[] = {
136   { 0,  "Success" },
137   { 1,  "Version not supported" },
138   { 2,  "Invalid request parameters" },
139   { 4,  "Duplicate LAN destination registration" },
140   { 5,  "Duplicate ATM address" },
141   { 6,  "Insufficient resources to grant request" },
142   { 7,  "Access denied" },
143   { 8,  "Invalid REQUESTOR-ID" },
144   { 9,  "Invalid LAN destination" },
145   { 10, "Invalid ATM address" },
146   { 20, "No configuration" },
147   { 21, "LE_CONFIGURE error" },
148   { 22, "Insufficient information" },
149   { 24, "TLV not found" },
150   { 0,  NULL }
151 };
152
153 /* LE Control LAN destination tags */
154 #define TAG_NOT_PRESENT         0x0000
155 #define TAG_MAC_ADDRESS         0x0001
156 #define TAG_ROUTE_DESCRIPTOR    0x0002
157
158 static const value_string le_control_landest_tag_vals[] = {
159   { TAG_NOT_PRESENT,       "Not present" },
160   { TAG_MAC_ADDRESS,       "MAC address" },
161   { TAG_ROUTE_DESCRIPTOR,  "Route descriptor" },
162   { 0,                     NULL }
163 };
164
165 /* LE Control LAN types */
166 #define LANT_UNSPEC     0x00
167 #define LANT_802_3      0x01
168 #define LANT_802_5      0x02
169
170 static const value_string le_control_lan_type_vals[] = {
171   { LANT_UNSPEC, "Unspecified" },
172   { LANT_802_3,  "Ethernet/802.3" },
173   { LANT_802_5,  "802.5" },
174   { 0,           NULL }
175 };
176
177 static const value_string le_control_frame_size_vals[] = {
178   { 0x00, "Unspecified" },
179   { 0x01, "1516/1528/1580/1592" },
180   { 0x02, "4544/4556/1580/1592" },
181   { 0x03, "9234/9246" },
182   { 0x04, "18190/18202" },
183   { 0,    NULL }
184 };
185
186 static void
187 dissect_le_client(tvbuff_t *tvb, proto_tree *tree)
188 {
189   proto_item *ti;
190   proto_tree *lane_tree;
191
192   if (tree) {
193     ti = proto_tree_add_protocol_format(tree, proto_atm_lane, tvb, 0, 2, "ATM LANE");
194     lane_tree = proto_item_add_subtree(ti, ett_atm_lane);
195
196     proto_tree_add_text(lane_tree, tvb, 0, 2, "LE Client: 0x%04X",
197                         tvb_get_ntohs(tvb, 0));
198   }
199 }
200
201 static void
202 dissect_lan_destination(tvbuff_t *tvb, int offset, const char *type, proto_tree *tree)
203 {
204   proto_item *td;
205   proto_tree *dest_tree;
206   guint16 tag;
207   proto_tree *rd_tree;
208   guint16 route_descriptor;
209
210   td = proto_tree_add_text(tree, tvb, offset, 8, "%s LAN destination",
211                            type);
212   dest_tree = proto_item_add_subtree(td, ett_atm_lane_lc_lan_dest);
213   tag = tvb_get_ntohs(tvb, offset);
214   proto_tree_add_text(dest_tree, tvb, offset, 2, "Tag: %s",
215                       val_to_str(tag, le_control_landest_tag_vals,
216                                  "Unknown (0x%04X)"));
217   offset += 2;
218
219   switch (tag) {
220
221   case TAG_MAC_ADDRESS:
222     proto_tree_add_text(dest_tree, tvb, offset, 6, "MAC address: %s",
223                         tvb_ether_to_str(tvb, offset));
224     break;
225
226   case TAG_ROUTE_DESCRIPTOR:
227     offset += 4;
228     route_descriptor = tvb_get_ntohs(tvb, offset);
229     proto_tree_add_text(dest_tree, tvb, offset, 2, "Route descriptor: 0x%02X",
230                               route_descriptor);
231     rd_tree = proto_item_add_subtree(td, ett_atm_lane_lc_lan_dest_rd);
232     proto_tree_add_text(rd_tree, tvb, offset, 2, "%s",
233                         decode_numeric_bitfield(route_descriptor, 0xFFF0, 2*8,
234                                                 "LAN ID = %u"));
235     proto_tree_add_text(rd_tree, tvb, offset, 2, "%s",
236                         decode_numeric_bitfield(route_descriptor, 0x000F, 2*8,
237                                                 "Bridge number = %u"));
238     break;
239   }
240 }
241
242 /*
243  * TLV values in LE Control frames.
244  */
245 #define TLV_TYPE(oui, ident)            (((oui) << 8) | (ident))
246
247 #define LE_CONTROL_TIMEOUT              TLV_TYPE(OUI_ATM_FORUM, 0x01)
248 #define LE_MAX_UNK_FRAME_COUNT          TLV_TYPE(OUI_ATM_FORUM, 0x02)
249 #define LE_MAX_UNK_FRAME_TIME           TLV_TYPE(OUI_ATM_FORUM, 0x03)
250 #define LE_VCC_TIMEOUT_PERIOD           TLV_TYPE(OUI_ATM_FORUM, 0x04)
251 #define LE_MAX_RETRY_COUNT              TLV_TYPE(OUI_ATM_FORUM, 0x05)
252 #define LE_AGING_TIME                   TLV_TYPE(OUI_ATM_FORUM, 0x06)
253 #define LE_FORWARD_DELAY_TIME           TLV_TYPE(OUI_ATM_FORUM, 0x07)
254 #define LE_EXPECTED_ARP_RESPONSE_TIME   TLV_TYPE(OUI_ATM_FORUM, 0x08)
255 #define LE_FLUSH_TIMEOUT                TLV_TYPE(OUI_ATM_FORUM, 0x09)
256 #define LE_PATH_SWITCHING_DELAY         TLV_TYPE(OUI_ATM_FORUM, 0x0A)
257 #define LE_LOCAL_SEGMENT_ID             TLV_TYPE(OUI_ATM_FORUM, 0x0B)
258 #define LE_MCAST_SEND_VCC_TYPE          TLV_TYPE(OUI_ATM_FORUM, 0x0C)
259 #define LE_MCAST_SEND_VCC_AVGRATE       TLV_TYPE(OUI_ATM_FORUM, 0x0D)
260 #define LE_MCAST_SEND_VCC_PEAKRATE      TLV_TYPE(OUI_ATM_FORUM, 0x0E)
261 #define LE_CONN_COMPLETION_TIMER        TLV_TYPE(OUI_ATM_FORUM, 0x0F)
262 #define LE_CONFIG_FRAG_INFO             TLV_TYPE(OUI_ATM_FORUM, 0x10)
263 #define LE_LAYER_3_ADDRESS              TLV_TYPE(OUI_ATM_FORUM, 0x11)
264 #define LE_ELAN_ID                      TLV_TYPE(OUI_ATM_FORUM, 0x12)
265 #define LE_SERVICE_CATEGORY             TLV_TYPE(OUI_ATM_FORUM, 0x13)
266 #define LE_LLC_MUXED_ATM_ADDRESS        TLV_TYPE(OUI_ATM_FORUM, 0x2B)
267 #define LE_X5_ADJUSTMENT                TLV_TYPE(OUI_ATM_FORUM, 0x2C)
268 #define LE_PREFERRED_LES                TLV_TYPE(OUI_ATM_FORUM, 0x2D)
269
270 static const value_string le_tlv_type_vals[] = {
271   { LE_CONTROL_TIMEOUT,           "Control Time-out" },
272   { LE_MAX_UNK_FRAME_COUNT,       "Maximum Unknown Frame Count" },
273   { LE_MAX_UNK_FRAME_TIME,        "Maximum Unknown Frame Time" },
274   { LE_VCC_TIMEOUT_PERIOD,        "VCC Time-out" },
275   { LE_MAX_RETRY_COUNT,           "Maximum Retry Count" },
276   { LE_AGING_TIME,                "Aging Time" },
277   { LE_FORWARD_DELAY_TIME,        "Forwarding Delay Time" },
278   { LE_EXPECTED_ARP_RESPONSE_TIME, "Expected LE_ARP Response Time" },
279   { LE_FLUSH_TIMEOUT,             "Flush Time-out" },
280   { LE_PATH_SWITCHING_DELAY,      "Path Switching Delay" },
281   { LE_LOCAL_SEGMENT_ID,          "Local Segment ID" },
282   { LE_MCAST_SEND_VCC_TYPE,       "Mcast Send VCC Type" },
283   { LE_MCAST_SEND_VCC_AVGRATE,    "Mcast Send VCC AvgRate" },
284   { LE_MCAST_SEND_VCC_PEAKRATE,   "Mcast Send VCC PeakRate" },
285   { LE_CONN_COMPLETION_TIMER,     "Connection Completion Timer" },
286   { LE_CONFIG_FRAG_INFO,          "Config Frag Info" },
287   { LE_LAYER_3_ADDRESS,           "Layer 3 Address" },
288   { LE_ELAN_ID,                   "ELAN ID" },
289   { LE_SERVICE_CATEGORY,          "Service Category" },
290   { LE_LLC_MUXED_ATM_ADDRESS,     "LLC-muxed ATM Address" },
291   { LE_X5_ADJUSTMENT,             "X5 Adjustment" },
292   { LE_PREFERRED_LES,             "Preferred LES" },
293   { 0,                            NULL },
294 };
295
296 static void
297 dissect_le_control_tlvs(tvbuff_t *tvb, int offset, guint num_tlvs,
298                         proto_tree *tree)
299 {
300   guint32 tlv_type;
301   guint8 tlv_length;
302   proto_item *ttlv;
303   proto_tree *tlv_tree;
304
305   while (num_tlvs != 0) {
306     tlv_type = tvb_get_ntohl(tvb, offset);
307     tlv_length = tvb_get_guint8(tvb, offset+4);
308     ttlv = proto_tree_add_text(tree, tvb, offset, 5+tlv_length, "TLV type: %s",
309                                val_to_str(tlv_type, le_tlv_type_vals, "Unknown (0x%08x)"));
310     tlv_tree = proto_item_add_subtree(ttlv, ett_atm_lane_lc_tlv);
311     proto_tree_add_text(tlv_tree, tvb, offset, 4, "TLV Type: %s",
312                         val_to_str(tlv_type, le_tlv_type_vals, "Unknown (0x%08x)"));
313     proto_tree_add_text(tlv_tree, tvb, offset+4, 1, "TLV Length: %u", tlv_length);
314     offset += 5+tlv_length;
315     num_tlvs--;
316   }
317 }
318
319 static void
320 dissect_le_configure_join_frame(tvbuff_t *tvb, int offset, proto_tree *tree)
321 {
322   guint8 num_tlvs;
323   guint8 name_size;
324
325   dissect_lan_destination(tvb, offset, "Source", tree);
326   offset += 8;
327
328   dissect_lan_destination(tvb, offset, "Target", tree);
329   offset += 8;
330
331   proto_tree_add_text(tree, tvb, offset, 20, "Source ATM Address: %s",
332                       tvb_bytes_to_str(tvb, offset, 20));
333   offset += 20;
334
335   proto_tree_add_text(tree, tvb, offset, 1, "LAN type: %s",
336                       val_to_str(tvb_get_guint8(tvb, offset), le_control_lan_type_vals,
337                                  "Unknown (0x%02X)"));
338   offset += 1;
339
340   proto_tree_add_text(tree, tvb, offset, 1, "Maximum frame size: %s",
341                       val_to_str(tvb_get_guint8(tvb, offset), le_control_frame_size_vals,
342                                  "Unknown (0x%02X)"));
343   offset += 1;
344
345   num_tlvs = tvb_get_guint8(tvb, offset);
346   proto_tree_add_text(tree, tvb, offset, 1, "Number of TLVs: %u", num_tlvs);
347   offset += 1;
348
349   name_size = tvb_get_guint8(tvb, offset);
350   proto_tree_add_text(tree, tvb, offset, 1, "ELAN name size: %u", name_size);
351   offset += 1;
352
353   proto_tree_add_text(tree, tvb, offset, 20, "Target ATM Address: %s",
354                       tvb_bytes_to_str(tvb, offset, 20));
355   offset += 20;
356
357   if (name_size > 32)
358     name_size = 32;
359   if (name_size != 0) {
360     proto_tree_add_text(tree, tvb, offset, name_size, "ELAN name: %s",
361                         tvb_bytes_to_str(tvb, offset, name_size));
362   }
363   offset += 32;
364
365   dissect_le_control_tlvs(tvb, offset, num_tlvs, tree);
366 }
367
368 static void
369 dissect_le_registration_frame(tvbuff_t *tvb, int offset, proto_tree *tree)
370 {
371   guint8 num_tlvs;
372
373   dissect_lan_destination(tvb, offset, "Source", tree);
374   offset += 8;
375
376   dissect_lan_destination(tvb, offset, "Target", tree);
377   offset += 8;
378
379   proto_tree_add_text(tree, tvb, offset, 20, "Source ATM Address: %s",
380                       tvb_bytes_to_str(tvb, offset, 20));
381   offset += 20;
382
383   /* Reserved */
384   offset += 2;
385
386   num_tlvs = tvb_get_guint8(tvb, offset);
387   proto_tree_add_text(tree, tvb, offset, 1, "Number of TLVs: %u", num_tlvs);
388   offset += 1;
389
390   /* Reserved */
391   offset += 53;
392
393   dissect_le_control_tlvs(tvb, offset, num_tlvs, tree);
394 }
395
396 static void
397 dissect_le_arp_frame(tvbuff_t *tvb, int offset, proto_tree *tree)
398 {
399   guint8 num_tlvs;
400
401   dissect_lan_destination(tvb, offset, "Source", tree);
402   offset += 8;
403
404   dissect_lan_destination(tvb, offset, "Target", tree);
405   offset += 8;
406
407   proto_tree_add_text(tree, tvb, offset, 20, "Source ATM Address: %s",
408                       tvb_bytes_to_str(tvb, offset, 20));
409   offset += 20;
410
411   /* Reserved */
412   offset += 2;
413
414   num_tlvs = tvb_get_guint8(tvb, offset);
415   proto_tree_add_text(tree, tvb, offset, 1, "Number of TLVs: %u", num_tlvs);
416   offset += 1;
417
418   /* Reserved */
419   offset += 1;
420
421   proto_tree_add_text(tree, tvb, offset, 20, "Target ATM Address: %s",
422                       tvb_bytes_to_str(tvb, offset, 20));
423   offset += 20;
424
425   /* Reserved */
426   offset += 32;
427
428   dissect_le_control_tlvs(tvb, offset, num_tlvs, tree);
429 }
430
431 static void
432 dissect_le_verify_frame(tvbuff_t *tvb, int offset, proto_tree *tree)
433 {
434   guint8 num_tlvs;
435
436   /* Reserved */
437   offset += 38;
438
439   num_tlvs = tvb_get_guint8(tvb, offset);
440   proto_tree_add_text(tree, tvb, offset, 1, "Number of TLVs: %u", num_tlvs);
441   offset += 1;
442
443   /* Reserved */
444   offset += 1;
445
446   proto_tree_add_text(tree, tvb, offset, 20, "Target ATM Address: %s",
447                       tvb_bytes_to_str(tvb, offset, 20));
448   offset += 20;
449
450   /* Reserved */
451   offset += 32;
452
453   dissect_le_control_tlvs(tvb, offset, num_tlvs, tree);
454 }
455
456 static void
457 dissect_le_flush_frame(tvbuff_t *tvb, int offset, proto_tree *tree)
458 {
459   dissect_lan_destination(tvb, offset, "Source", tree);
460   offset += 8;
461
462   dissect_lan_destination(tvb, offset, "Target", tree);
463   offset += 8;
464
465   proto_tree_add_text(tree, tvb, offset, 20, "Source ATM Address: %s",
466                       tvb_bytes_to_str(tvb, offset, 20));
467   offset += 20;
468
469   /* Reserved */
470   offset += 4;
471
472   proto_tree_add_text(tree, tvb, offset, 20, "Target ATM Address: %s",
473                       tvb_bytes_to_str(tvb, offset, 20));
474   offset += 20;
475
476   /* Reserved */
477   offset += 32;
478 }
479
480 static void
481 dissect_le_control(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
482 {
483   proto_item *ti;
484   proto_tree *lane_tree = NULL;
485   int offset = 0;
486   proto_item *tf;
487   proto_tree *flags_tree;
488   guint16 opcode;
489   guint16 flags;
490
491   col_set_str(pinfo->cinfo, COL_INFO, "LE Control");
492
493   if (tree) {
494     ti = proto_tree_add_protocol_format(tree, proto_atm_lane, tvb, offset, 108, "ATM LANE");
495     lane_tree = proto_item_add_subtree(ti, ett_atm_lane);
496
497     proto_tree_add_text(lane_tree, tvb, offset, 2, "Marker: 0x%04X",
498                         tvb_get_ntohs(tvb, offset));
499   }
500   offset += 2;
501
502   if (tree) {
503     proto_tree_add_text(lane_tree, tvb, offset, 1, "Protocol: 0x%02X",
504                         tvb_get_guint8(tvb, offset));
505   }
506   offset += 1;
507
508   if (tree) {
509     proto_tree_add_text(lane_tree, tvb, offset, 1, "Version: 0x%02X",
510                         tvb_get_guint8(tvb, offset));
511   }
512   offset += 1;
513
514   opcode = tvb_get_ntohs(tvb, offset);
515   col_append_fstr(pinfo->cinfo, COL_INFO, ": %s",
516                   val_to_str(opcode, le_control_opcode_vals,
517                              "Unknown opcode (0x%04X)"));
518
519   if (tree) {
520     proto_tree_add_text(lane_tree, tvb, offset, 2, "Opcode: %s",
521                         val_to_str(opcode, le_control_opcode_vals,
522                                    "Unknown (0x%04X)"));
523   }
524   offset += 2;
525
526   if (opcode == READY_QUERY || opcode == READY_IND) {
527     /* There's nothing more in this packet. */
528     return;
529   }
530
531   if (tree) {
532     if (opcode & 0x0100) {
533       /* Response; decode status. */
534       proto_tree_add_text(lane_tree, tvb, offset, 2, "Status: %s",
535                           val_to_str(tvb_get_ntohs(tvb, offset), le_control_status_vals,
536                                      "Unknown (0x%04X)"));
537     }
538     offset += 2;
539
540     proto_tree_add_text(lane_tree, tvb, offset, 4, "Transaction ID: 0x%08X",
541                         tvb_get_ntohl(tvb, offset));
542     offset += 4;
543
544     proto_tree_add_text(lane_tree, tvb, offset, 2, "Requester LECID: 0x%04X",
545                         tvb_get_ntohs(tvb, offset));
546     offset += 2;
547
548     flags = tvb_get_ntohs(tvb, offset);
549     tf = proto_tree_add_text(lane_tree, tvb, offset, 2, "Flags: 0x%04X",
550                              flags);
551     flags_tree = proto_item_add_subtree(tf, ett_atm_lane_lc_flags);
552
553     switch (opcode) {
554
555     case LE_CONFIGURE_REQUEST:
556     case LE_CONFIGURE_RESPONSE:
557       proto_tree_add_text(flags_tree, tvb, offset, 2, "%s",
558                           decode_boolean_bitfield(flags, 0x0002, 8*2,
559                                                   "V2 capable", "Not V2 capable"));
560       offset += 2;
561       dissect_le_configure_join_frame(tvb, offset, lane_tree);
562       break;
563
564     case LE_JOIN_REQUEST:
565     case LE_JOIN_RESPONSE:
566       proto_tree_add_text(flags_tree, tvb, offset, 2, "%s",
567                           decode_boolean_bitfield(flags, 0x0002, 8*2,
568                                                   "V2 capable", "Not V2 capable"));
569       if (opcode == LE_JOIN_REQUEST) {
570         proto_tree_add_text(flags_tree, tvb, offset, 2, "%s",
571                             decode_boolean_bitfield(flags, 0x0004, 8*2,
572                                                     "Selective multicast", "No selective multicast"));
573       } else {
574         proto_tree_add_text(flags_tree, tvb, offset, 2, "%s",
575                             decode_boolean_bitfield(flags, 0x0008, 8*2,
576                                         "V2 required", "V2 not required"));
577       }
578       proto_tree_add_text(flags_tree, tvb, offset, 2, "%s",
579         decode_boolean_bitfield(flags, 0x0080, 8*2,
580                                 "Proxy", "Not proxy"));
581       proto_tree_add_text(flags_tree, tvb, offset, 2, "%s",
582         decode_boolean_bitfield(flags, 0x0200, 8*2,
583                                 "Exclude explorer frames",
584                                 "Don't exclude explorer frames"));
585       offset += 2;
586       dissect_le_configure_join_frame(tvb, offset, lane_tree);
587       break;
588
589     case LE_REGISTER_REQUEST:
590     case LE_REGISTER_RESPONSE:
591     case LE_UNREGISTER_REQUEST:
592     case LE_UNREGISTER_RESPONSE:
593       offset += 2;
594       dissect_le_registration_frame(tvb, offset, lane_tree);
595       break;
596
597     case LE_ARP_REQUEST:
598     case LE_ARP_RESPONSE:
599     case LE_NARP_REQUEST:
600       if (opcode != LE_NARP_REQUEST) {
601         proto_tree_add_text(flags_tree, tvb, offset, 2, "%s",
602                             decode_boolean_bitfield(flags, 0x0001, 8*2,
603                                                     "Remote address", "Local address"));
604       }
605       offset += 2;
606       dissect_le_arp_frame(tvb, offset, lane_tree);
607       break;
608
609     case LE_TOPOLOGY_REQUEST:
610       proto_tree_add_text(flags_tree, tvb, offset, 2, "%s",
611                           decode_boolean_bitfield(flags, 0x0100, 8*2,
612                                                   "Topology change", "No topology change"));
613       offset += 2;
614       /* 92 reserved bytes */
615       break;
616
617     case LE_VERIFY_REQUEST:
618     case LE_VERIFY_RESPONSE:
619       offset += 2;
620       dissect_le_verify_frame(tvb, offset, lane_tree);
621       break;
622
623     case LE_FLUSH_REQUEST:
624     case LE_FLUSH_RESPONSE:
625       offset += 2;
626       dissect_le_flush_frame(tvb, offset, lane_tree);
627       break;
628     }
629   }
630 }
631
632 static void
633 capture_lane(const union wtap_pseudo_header *pseudo_header, const guchar *pd,
634     int len, packet_counts *ld)
635 {
636   /* Is it LE Control, 802.3, 802.5, or "none of the above"? */
637   switch (pseudo_header->atm.subtype) {
638
639   case TRAF_ST_LANE_802_3:
640   case TRAF_ST_LANE_802_3_MC:
641     /* Dissect as Ethernet */
642     capture_eth(pd, 2, len, ld);
643     break;
644
645   case TRAF_ST_LANE_802_5:
646   case TRAF_ST_LANE_802_5_MC:
647     /* Dissect as Token-Ring */
648     capture_tr(pd, 2, len, ld);
649     break;
650
651   default:
652     ld->other++;
653     break;
654   }
655 }
656
657 static void
658 dissect_lane(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
659 {
660   tvbuff_t *next_tvb;
661   tvbuff_t *next_tvb_le_client;
662
663   col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATM LANE");
664
665   /* Is it LE Control, 802.3, 802.5, or "none of the above"? */
666   switch (pinfo->pseudo_header->atm.subtype) {
667
668   case TRAF_ST_LANE_LE_CTRL:
669     dissect_le_control(tvb, pinfo, tree);
670     break;
671
672   case TRAF_ST_LANE_802_3:
673   case TRAF_ST_LANE_802_3_MC:
674     col_set_str(pinfo->cinfo, COL_INFO, "LE Client - Ethernet/802.3");
675     dissect_le_client(tvb, tree);
676
677     /* Dissect as Ethernet */
678     next_tvb_le_client  = tvb_new_subset_remaining(tvb, 2);
679     call_dissector(eth_withoutfcs_handle, next_tvb_le_client, pinfo, tree);
680     break;
681
682   case TRAF_ST_LANE_802_5:
683   case TRAF_ST_LANE_802_5_MC:
684     col_set_str(pinfo->cinfo, COL_INFO, "LE Client - 802.5");
685     dissect_le_client(tvb, tree);
686
687     /* Dissect as Token-Ring */
688     next_tvb_le_client  = tvb_new_subset_remaining(tvb, 2);
689     call_dissector(tr_handle, next_tvb_le_client, pinfo, tree);
690     break;
691
692   default:
693     /* Dump it as raw data. */
694     col_set_str(pinfo->cinfo, COL_INFO, "Unknown LANE traffic type");
695     next_tvb            = tvb_new_subset_remaining(tvb, 0);
696     call_dissector(data_handle,next_tvb, pinfo, tree);
697     break;
698   }
699 }
700
701 static void
702 dissect_ilmi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
703 {
704   dissect_snmp_pdu(tvb, 0, pinfo, tree, proto_ilmi, ett_ilmi, ENC_BIG_ENDIAN);
705 }
706
707 /* AAL types */
708 static const value_string aal_vals[] = {
709   { AAL_UNKNOWN,            "Unknown AAL" },
710   { AAL_1,                  "AAL1" },
711   { AAL_2,                  "AAL2" },
712   { AAL_3_4,                "AAL3/4" },
713   { AAL_5,                  "AAL5" },
714   { AAL_USER,               "User AAL" },
715   { AAL_SIGNALLING,         "Signalling AAL" },
716   { AAL_OAMCELL,            "OAM cell" },
717   { 0,              NULL }
718 };
719
720 /* AAL5 higher-level traffic types */
721 static const value_string aal5_hltype_vals[] = {
722   { TRAF_UNKNOWN,           "Unknown traffic type" },
723   { TRAF_LLCMX,             "LLC multiplexed" },
724   { TRAF_VCMX,              "VC multiplexed" },
725   { TRAF_LANE,              "LANE" },
726   { TRAF_ILMI,              "ILMI" },
727   { TRAF_FR,                "Frame Relay" },
728   { TRAF_SPANS,             "FORE SPANS" },
729   { TRAF_IPSILON,           "Ipsilon" },
730   { TRAF_GPRS_NS,           "GPRS NS" },
731   { 0,              NULL }
732 };
733
734 /* Traffic subtypes for VC multiplexed traffic */
735 static const value_string vcmx_type_vals[] = {
736   { TRAF_ST_UNKNOWN,        "Unknown VC multiplexed traffic type" },
737   { TRAF_ST_VCMX_802_3_FCS, "802.3 FCS" },
738   { TRAF_ST_VCMX_802_4_FCS, "802.4 FCS" },
739   { TRAF_ST_VCMX_802_5_FCS, "802.5 FCS" },
740   { TRAF_ST_VCMX_FDDI_FCS,  "FDDI FCS" },
741   { TRAF_ST_VCMX_802_6_FCS, "802.6 FCS" },
742   { TRAF_ST_VCMX_802_3,     "802.3" },
743   { TRAF_ST_VCMX_802_4,     "802.4" },
744   { TRAF_ST_VCMX_802_5,     "802.5" },
745   { TRAF_ST_VCMX_FDDI,      "FDDI" },
746   { TRAF_ST_VCMX_802_6,     "802.6" },
747   { TRAF_ST_VCMX_FRAGMENTS, "Fragments" },
748   { TRAF_ST_VCMX_BPDU,      "BPDU" },
749   { 0,                   NULL }
750 };
751
752 /* Traffic subtypes for LANE traffic */
753 static const value_string lane_type_vals[] = {
754   { TRAF_ST_UNKNOWN,        "Unknown LANE traffic type" },
755   { TRAF_ST_LANE_LE_CTRL,   "LE Control" },
756   { TRAF_ST_LANE_802_3,     "802.3" },
757   { TRAF_ST_LANE_802_5,     "802.5" },
758   { TRAF_ST_LANE_802_3_MC,  "802.3 multicast" },
759   { TRAF_ST_LANE_802_5_MC,  "802.5 multicast" },
760   { 0,                     NULL }
761 };
762
763 /* Traffic subtypes for Ipsilon traffic */
764 static const value_string ipsilon_type_vals[] = {
765   { TRAF_ST_UNKNOWN,        "Unknown Ipsilon traffic type" },
766   { TRAF_ST_IPSILON_FT0,    "Flow type 0" },
767   { TRAF_ST_IPSILON_FT1,    "Flow type 1" },
768   { TRAF_ST_IPSILON_FT2,    "Flow type 2" },
769   { 0,                NULL }
770 };
771
772 void
773 capture_atm(const union wtap_pseudo_header *pseudo_header, const guchar *pd,
774     int len, packet_counts *ld)
775 {
776   if (pseudo_header->atm.aal == AAL_5) {
777     switch (pseudo_header->atm.type) {
778
779     case TRAF_LLCMX:
780       /* Dissect as WTAP_ENCAP_ATM_RFC1483 */
781       /* The ATM iptrace capture that we have shows LLC at this point,
782        * so that's what I'm calling */
783       capture_llc(pd, 0, len, ld);
784       break;
785
786     case TRAF_LANE:
787       capture_lane(pseudo_header, pd, len, ld);
788       break;
789
790     default:
791       ld->other++;
792       break;
793     }
794   } else
795     ld->other++;
796 }
797
798 /*
799  * Charles Michael Heard's CRC-32 code, from
800  *
801  *      http://www.cell-relay.com/cell-relay/publications/software/CRC/32bitCRC.c.html
802  *
803  * with the CRC table initialized with values computed by
804  * his "gen_crc_table()" routine, rather than by calling that routine
805  * at run time, and with various data type cleanups.
806  */
807
808 /* crc32h.c -- package to compute 32-bit CRC one byte at a time using   */
809 /*             the high-bit first (Big-Endian) bit ordering convention  */
810 /*                                                                      */
811 /* Synopsis:                                                            */
812 /*  gen_crc_table() -- generates a 256-word table containing all CRC    */
813 /*                     remainders for every possible 8-bit byte.  It    */
814 /*                     must be executed (once) before any CRC updates.  */
815 /*                                                                      */
816 /*  unsigned update_crc(crc_accum, data_blk_ptr, data_blk_size)         */
817 /*           unsigned crc_accum; char *data_blk_ptr; int data_blk_size; */
818 /*           Returns the updated value of the CRC accumulator after     */
819 /*           processing each byte in the addressed block of data.       */
820 /*                                                                      */
821 /*  It is assumed that an unsigned long is at least 32 bits wide and    */
822 /*  that the predefined type char occupies one 8-bit byte of storage.   */
823 /*                                                                      */
824 /*  The generator polynomial used for this version of the package is    */
825 /*  x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x^1+x^0 */
826 /*  as specified in the Autodin/Ethernet/ADCCP protocol standards.      */
827 /*  Other degree 32 polynomials may be substituted by re-defining the   */
828 /*  symbol POLYNOMIAL below.  Lower degree polynomials must first be    */
829 /*  multiplied by an appropriate power of x.  The representation used   */
830 /*  is that the coefficient of x^0 is stored in the LSB of the 32-bit   */
831 /*  word and the coefficient of x^31 is stored in the most significant  */
832 /*  bit.  The CRC is to be appended to the data most significant byte   */
833 /*  first.  For those protocols in which bytes are transmitted MSB      */
834 /*  first and in the same order as they are encountered in the block    */
835 /*  this convention results in the CRC remainder being transmitted with */
836 /*  the coefficient of x^31 first and with that of x^0 last (just as    */
837 /*  would be done by a hardware shift register mechanization).          */
838 /*                                                                      */
839 /*  The table lookup technique was adapted from the algorithm described */
840 /*  by Avram Perez, Byte-wise CRC Calculations, IEEE Micro 3, 40 (1983).*/
841
842 static const guint32 crc_table[256] = {
843   0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
844   0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
845   0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
846   0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
847   0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,
848   0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
849   0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011,
850   0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
851   0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
852   0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
853   0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,
854   0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
855   0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49,
856   0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
857   0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
858   0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
859   0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,
860   0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
861   0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
862   0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
863   0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
864   0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
865   0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,
866   0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
867   0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e,
868   0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
869   0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
870   0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
871   0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
872   0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
873   0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686,
874   0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
875   0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
876   0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
877   0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,
878   0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
879   0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47,
880   0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
881   0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
882   0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
883   0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,
884   0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
885   0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f,
886   0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
887   0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
888   0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
889   0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,
890   0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
891   0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
892   0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
893   0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
894   0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
895   0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
896   0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
897   0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,
898   0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
899   0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
900   0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
901   0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
902   0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
903   0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,
904   0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
905   0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
906   0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4,
907 };
908
909 static guint32
910 update_crc(guint32 crc_accum, const guint8 *data_blk_ptr, int data_blk_size)
911 {
912   register int i, j;
913
914   /* update the CRC on the data block one byte at a time */
915   for (j = 0; j < data_blk_size;  j++) {
916     i = ( (int) ( crc_accum >> 24) ^ *data_blk_ptr++ ) & 0xff;
917     crc_accum = ( crc_accum << 8 ) ^ crc_table[i];
918   }
919   return crc_accum;
920 }
921
922 static void
923 dissect_reassembled_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
924     proto_item *atm_ti,
925     proto_tree *atm_tree, gboolean truncated)
926 {
927   guint        length, reported_length;
928   guint16      aal5_length;
929   int          pad_length;
930   tvbuff_t     *next_tvb;
931   guint32      crc;
932   guint32      calc_crc;
933   gint         type;
934   /*
935    * ATM dissector is used as "sub-dissector" for ATM pseudowires.
936    * In such cases, pinfo->private_data is used to pass info from/to
937    * PW dissector to ATM dissector. For decoding normal ATM traffic
938    * private_data should be NULL.
939    */
940   gboolean     pseudowire_mode = (NULL != pinfo->private_data);
941
942   /*
943    * This is reassembled traffic, so the cell headers are missing;
944    * show the traffic type for AAL5 traffic, and the VPI and VCI,
945    * from the pseudo-header.
946    */
947   if (pinfo->pseudo_header->atm.aal == AAL_5) {
948     proto_tree_add_text(atm_tree, tvb, 0, 0, "Traffic type: %s",
949                         val_to_str(pinfo->pseudo_header->atm.type, aal5_hltype_vals,
950                                    "Unknown AAL5 traffic type (%u)"));
951     switch (pinfo->pseudo_header->atm.type) {
952
953     case TRAF_VCMX:
954       proto_tree_add_text(atm_tree, tvb, 0, 0, "VC multiplexed traffic type: %s",
955                           val_to_str(pinfo->pseudo_header->atm.subtype,
956                                      vcmx_type_vals, "Unknown VCMX traffic type (%u)"));
957       break;
958
959     case TRAF_LANE:
960       proto_tree_add_text(atm_tree, tvb, 0, 0, "LANE traffic type: %s",
961                           val_to_str(pinfo->pseudo_header->atm.subtype,
962                                      lane_type_vals, "Unknown LANE traffic type (%u)"));
963       break;
964
965     case TRAF_IPSILON:
966       proto_tree_add_text(atm_tree, tvb, 0, 0, "Ipsilon traffic type: %s",
967                           val_to_str(pinfo->pseudo_header->atm.subtype,
968                                      ipsilon_type_vals, "Unknown Ipsilon traffic type (%u)"));
969       break;
970     }
971   }
972   if (!pseudowire_mode) {
973     proto_tree_add_uint(atm_tree, hf_atm_vpi, tvb, 0, 0,
974                         pinfo->pseudo_header->atm.vpi);
975     proto_tree_add_uint(atm_tree, hf_atm_vci, tvb, 0, 0,
976                         pinfo->pseudo_header->atm.vci);
977
978     /* Also show vpi/vci in info column */
979     col_append_fstr(pinfo->cinfo, COL_INFO, " VPI=%u, VCI=%u",
980                     pinfo->pseudo_header->atm.vpi,
981                     pinfo->pseudo_header->atm.vci);
982   }
983
984   next_tvb = tvb;
985   if (truncated) {
986     /*
987      * The packet data does not include stuff such as the AAL5
988      * trailer.
989      */
990     if (pinfo->pseudo_header->atm.cells != 0) {
991       /*
992        * If the cell count is 0, assume it means we don't know how
993        * many cells it was.
994        *
995        * XXX - also assume it means we don't know what was in the AAL5
996        * trailer.  We may, however, find some capture program that can
997        * give us the AAL5 trailer information but not the cell count,
998        * in which case we need some other way of indicating whether we
999        * have the AAL5 trailer information.
1000        */
1001       if (tree) {
1002         proto_tree_add_text(atm_tree, tvb, 0, 0, "Cells: %u",
1003                             pinfo->pseudo_header->atm.cells);
1004         proto_tree_add_text(atm_tree, tvb, 0, 0, "AAL5 UU: 0x%02x",
1005                             pinfo->pseudo_header->atm.aal5t_u2u >> 8);
1006         proto_tree_add_text(atm_tree, tvb, 0, 0, "AAL5 CPI: 0x%02x",
1007                             pinfo->pseudo_header->atm.aal5t_u2u & 0xFF);
1008         proto_tree_add_text(atm_tree, tvb, 0, 0, "AAL5 len: %u",
1009                             pinfo->pseudo_header->atm.aal5t_len);
1010         proto_tree_add_text(atm_tree, tvb, 0, 0, "AAL5 CRC: 0x%08X",
1011                             pinfo->pseudo_header->atm.aal5t_chksum);
1012       }
1013     }
1014   } else {
1015     /*
1016      * The packet data includes stuff such as the AAL5 trailer, if
1017      * it wasn't cut off by the snapshot length.
1018      * Decode the trailer, if present, and then chop it off.
1019      */
1020     length = tvb_length(tvb);
1021     reported_length = tvb_reported_length(tvb);
1022     if ((reported_length % 48) == 0) {
1023       /*
1024        * Reported length is a multiple of 48, so we can presumably
1025        * divide it by 48 to get the number of cells.
1026        */
1027       proto_tree_add_text(atm_tree, tvb, 0, 0, "Cells: %u",
1028                           reported_length/48);
1029     }
1030     if ((pinfo->pseudo_header->atm.aal == AAL_5 ||
1031          pinfo->pseudo_header->atm.aal == AAL_SIGNALLING) &&
1032         length >= reported_length) {
1033       /*
1034        * XXX - what if the packet is truncated?  Can that happen?
1035        * What if you capture with Windows Sniffer on an ATM link
1036        * and tell it not to save the entire packet?  What happens
1037        * to the trailer?
1038        */
1039       aal5_length = tvb_get_ntohs(tvb, length - 6);
1040
1041       /*
1042        * Check for sanity in the AAL5 length.  It must be > 0
1043        * and must be less than the amount of space left after
1044        * we remove the trailer.
1045        *
1046        * If it's not sane, assume we don't have a trailer.
1047        */
1048       if (aal5_length > 0 && aal5_length <= length - 8) {
1049         /*
1050          * How much padding is there?
1051          */
1052         pad_length = length - aal5_length - 8;
1053
1054         /*
1055          * There is no reason for more than 47 bytes of padding.
1056          * The most padding you can have would be 7 bytes at the
1057          * end of the next-to-last cell (8 bytes after the end of
1058          * the data means you can fit the trailer in that cell),
1059          * plus 40 bytes in the last cell (with the last 8 bytes
1060          * being padding).
1061          *
1062          * If there's more than 47 bytes of padding, assume we don't
1063          * have a trailer.
1064          */
1065         if (pad_length <= 47) {
1066           if (tree) {
1067             if (pad_length > 0) {
1068               proto_tree_add_text(atm_tree, tvb, aal5_length, pad_length,
1069                                   "Padding");
1070             }
1071             proto_tree_add_text(atm_tree, tvb, length - 8, 1, "AAL5 UU: 0x%02x",
1072                                 tvb_get_guint8(tvb, length - 8));
1073             proto_tree_add_text(atm_tree, tvb, length - 7, 1, "AAL5 CPI: 0x%02x",
1074                                 tvb_get_guint8(tvb, length - 7));
1075             proto_tree_add_text(atm_tree, tvb, length - 6, 2, "AAL5 len: %u",
1076                                 aal5_length);
1077             crc = tvb_get_ntohl(tvb, length - 4);
1078             calc_crc = update_crc(0xFFFFFFFF, tvb_get_ptr(tvb, 0, length),
1079                                   length);
1080             proto_tree_add_text(atm_tree, tvb, length - 4, 4,
1081                                 "AAL5 CRC: 0x%08X (%s)", crc,
1082                                 (calc_crc == 0xC704DD7B) ? "correct" : "incorrect");
1083           }
1084           next_tvb = tvb_new_subset(tvb, 0, aal5_length, aal5_length);
1085         }
1086       }
1087     }
1088   }
1089
1090   switch (pinfo->pseudo_header->atm.aal) {
1091
1092   case AAL_SIGNALLING:
1093     call_dissector(sscop_handle, next_tvb, pinfo, tree);
1094     break;
1095
1096   case AAL_5:
1097     switch (pinfo->pseudo_header->atm.type) {
1098
1099     case TRAF_FR:
1100       call_dissector(fr_handle, next_tvb, pinfo, tree);
1101       break;
1102
1103     case TRAF_LLCMX:
1104       call_dissector(llc_handle, next_tvb, pinfo, tree);
1105       break;
1106
1107     case TRAF_LANE:
1108       call_dissector(lane_handle, next_tvb, pinfo, tree);
1109       break;
1110
1111     case TRAF_ILMI:
1112       call_dissector(ilmi_handle, next_tvb, pinfo, tree);
1113       break;
1114
1115     case TRAF_GPRS_NS:
1116       call_dissector(gprs_ns_handle, next_tvb, pinfo, tree);
1117       break;
1118
1119     default:
1120       {
1121         gboolean decoded = FALSE;
1122
1123         if (tvb_length(next_tvb) > 7) /* sizeof(octet) */
1124         {
1125             guint8 octet[8];
1126             tvb_memcpy(next_tvb, octet, 0, sizeof(octet));
1127
1128             decoded = TRUE;
1129             if (octet[0] == 0xaa
1130              && octet[1] == 0xaa
1131              && octet[2] == 0x03) /* LLC SNAP as per RFC2684 */
1132             {
1133                 call_dissector(llc_handle, next_tvb, pinfo, tree);
1134             }
1135             else if ((pntohs(octet) & 0xff) == PPP_IP)
1136             {
1137                 call_dissector(ppp_handle, next_tvb, pinfo, tree);
1138             }
1139             else if (pntohs(octet) == 0x00)
1140             {
1141                 /* assume vc muxed bridged ethernet */
1142                 proto_tree_add_text(tree, tvb, 0, 2, "Pad: 0x0000");
1143                 next_tvb = tvb_new_subset_remaining(tvb, 2);
1144                 call_dissector(eth_handle, next_tvb, pinfo, tree);
1145             }
1146             else if (octet[2] == 0x03    && /* NLPID */
1147                     ((octet[3] == 0xcc   || /* IPv4  */
1148                       octet[3] == 0x8e)  || /* IPv6  */
1149                      (octet[3] == 0x00   && /* Eth   */
1150                       octet[4] == 0x80)))   /* Eth   */
1151             {
1152                 /* assume network interworking with FR 2 byte header */
1153                 call_dissector(fr_handle, next_tvb, pinfo, tree);
1154             }
1155             else if (octet[4] == 0x03    && /* NLPID */
1156                     ((octet[5] == 0xcc   || /* IPv4  */
1157                       octet[5] == 0x8e)  || /* IPv6  */
1158                      (octet[5] == 0x00   && /* Eth   */
1159                       octet[6] == 0x80)))   /* Eth   */
1160             {
1161                 /* assume network interworking with FR 4 byte header */
1162                 call_dissector(fr_handle, next_tvb, pinfo, tree);
1163             }
1164             else if (((octet[0] & 0xf0)== 0x40) ||
1165                      ((octet[0] & 0xf0) == 0x60))
1166             {
1167                 call_dissector(ip_handle, next_tvb, pinfo, tree);
1168             }
1169             else
1170             {
1171                 decoded = FALSE;
1172             }
1173         }
1174
1175         if (tree && !decoded) {
1176             /* Dump it as raw data. */
1177             call_dissector(data_handle, next_tvb, pinfo, tree);
1178         }
1179       }
1180       break;
1181     }
1182     break;
1183
1184   case AAL_2:
1185     proto_tree_add_uint(atm_tree, hf_atm_cid, tvb, 0, 0,
1186                         pinfo->pseudo_header->atm.aal2_cid);
1187     proto_item_append_text(atm_ti, " (vpi=%u vci=%u cid=%u)",
1188                            pinfo->pseudo_header->atm.vpi,
1189                            pinfo->pseudo_header->atm.vci,
1190                            pinfo->pseudo_header->atm.aal2_cid);
1191
1192     if (pinfo->pseudo_header->atm.flags & ATM_AAL2_NOPHDR) {
1193       next_tvb = tvb;
1194     } else {
1195           /* Skip first 4 bytes of message
1196              - side
1197              - length
1198              - UUI
1199              Ignoring for now... */
1200       next_tvb = tvb_new_subset_remaining(tvb, 4);
1201     }
1202
1203     type = pinfo->pseudo_header->atm.type;
1204     if (type == TRAF_UNKNOWN) {
1205       type = unknown_aal2_type;
1206     }
1207     switch (type) {
1208       case TRAF_UMTS_FP:
1209           call_dissector(fp_handle, next_tvb, pinfo, tree);
1210           break;
1211
1212       default:
1213         if (tree) {
1214           /* Dump it as raw data. */
1215           call_dissector(data_handle, next_tvb, pinfo, tree);
1216           break;
1217         }
1218     }
1219     break;
1220
1221   default:
1222     if (tree) {
1223       /* Dump it as raw data. */
1224       call_dissector(data_handle, next_tvb, pinfo, tree);
1225     }
1226     break;
1227   }
1228 }
1229
1230 /*
1231  * Charles Michael Heard's HEC code, from
1232  *
1233  *      http://www.cell-relay.com/cell-relay/publications/software/CRC/32bitCRC.tutorial.html
1234  *
1235  * with the syndrome and error position tables initialized with values
1236  * computed by his "gen_syndrome_table()" and "gen_err_posn_table()" routines,
1237  * rather than by calling those routines at run time, and with various data
1238  * type cleanups and changes not to correct the header if a correctible
1239  * error was detected.
1240  */
1241 #define COSET_LEADER    0x055               /* x^6 + x^4 + x^2 + 1  */
1242
1243 static const guint8 syndrome_table[256] = {
1244   0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15,
1245   0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d,
1246   0x70, 0x77, 0x7e, 0x79, 0x6c, 0x6b, 0x62, 0x65,
1247   0x48, 0x4f, 0x46, 0x41, 0x54, 0x53, 0x5a, 0x5d,
1248   0xe0, 0xe7, 0xee, 0xe9, 0xfc, 0xfb, 0xf2, 0xf5,
1249   0xd8, 0xdf, 0xd6, 0xd1, 0xc4, 0xc3, 0xca, 0xcd,
1250   0x90, 0x97, 0x9e, 0x99, 0x8c, 0x8b, 0x82, 0x85,
1251   0xa8, 0xaf, 0xa6, 0xa1, 0xb4, 0xb3, 0xba, 0xbd,
1252   0xc7, 0xc0, 0xc9, 0xce, 0xdb, 0xdc, 0xd5, 0xd2,
1253   0xff, 0xf8, 0xf1, 0xf6, 0xe3, 0xe4, 0xed, 0xea,
1254   0xb7, 0xb0, 0xb9, 0xbe, 0xab, 0xac, 0xa5, 0xa2,
1255   0x8f, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9d, 0x9a,
1256   0x27, 0x20, 0x29, 0x2e, 0x3b, 0x3c, 0x35, 0x32,
1257   0x1f, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0d, 0x0a,
1258   0x57, 0x50, 0x59, 0x5e, 0x4b, 0x4c, 0x45, 0x42,
1259   0x6f, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7d, 0x7a,
1260   0x89, 0x8e, 0x87, 0x80, 0x95, 0x92, 0x9b, 0x9c,
1261   0xb1, 0xb6, 0xbf, 0xb8, 0xad, 0xaa, 0xa3, 0xa4,
1262   0xf9, 0xfe, 0xf7, 0xf0, 0xe5, 0xe2, 0xeb, 0xec,
1263   0xc1, 0xc6, 0xcf, 0xc8, 0xdd, 0xda, 0xd3, 0xd4,
1264   0x69, 0x6e, 0x67, 0x60, 0x75, 0x72, 0x7b, 0x7c,
1265   0x51, 0x56, 0x5f, 0x58, 0x4d, 0x4a, 0x43, 0x44,
1266   0x19, 0x1e, 0x17, 0x10, 0x05, 0x02, 0x0b, 0x0c,
1267   0x21, 0x26, 0x2f, 0x28, 0x3d, 0x3a, 0x33, 0x34,
1268   0x4e, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5c, 0x5b,
1269   0x76, 0x71, 0x78, 0x7f, 0x6a, 0x6d, 0x64, 0x63,
1270   0x3e, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2c, 0x2b,
1271   0x06, 0x01, 0x08, 0x0f, 0x1a, 0x1d, 0x14, 0x13,
1272   0xae, 0xa9, 0xa0, 0xa7, 0xb2, 0xb5, 0xbc, 0xbb,
1273   0x96, 0x91, 0x98, 0x9f, 0x8a, 0x8d, 0x84, 0x83,
1274   0xde, 0xd9, 0xd0, 0xd7, 0xc2, 0xc5, 0xcc, 0xcb,
1275   0xe6, 0xe1, 0xe8, 0xef, 0xfa, 0xfd, 0xf4, 0xf3,
1276 };
1277
1278 #define NO_ERROR_DETECTED   -128
1279 #define UNCORRECTIBLE_ERROR  128
1280
1281 static const int err_posn_table[256] = {
1282   NO_ERROR_DETECTED,      39,
1283   38,                     UNCORRECTIBLE_ERROR,
1284   37,                     UNCORRECTIBLE_ERROR,
1285   UNCORRECTIBLE_ERROR,    31,
1286   36,                     UNCORRECTIBLE_ERROR,
1287   UNCORRECTIBLE_ERROR,    8,
1288   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1289   30,                     UNCORRECTIBLE_ERROR,
1290   35,                     UNCORRECTIBLE_ERROR,
1291   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1292   UNCORRECTIBLE_ERROR,    23,
1293   7,                      UNCORRECTIBLE_ERROR,
1294   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1295   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1296   29,                     UNCORRECTIBLE_ERROR,
1297   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1298   34,                     UNCORRECTIBLE_ERROR,
1299   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1300   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1301   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1302   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1303   22,                     UNCORRECTIBLE_ERROR,
1304   6,                      UNCORRECTIBLE_ERROR,
1305   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1306   UNCORRECTIBLE_ERROR,    0,
1307   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1308   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1309   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1310   28,                     UNCORRECTIBLE_ERROR,
1311   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1312   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1313   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1314   33,                     UNCORRECTIBLE_ERROR,
1315   UNCORRECTIBLE_ERROR,    10,
1316   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1317   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1318   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1319   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1320   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1321   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1322   UNCORRECTIBLE_ERROR,    12,
1323   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1324   21,                     UNCORRECTIBLE_ERROR,
1325   UNCORRECTIBLE_ERROR,    19,
1326   5,                      UNCORRECTIBLE_ERROR,
1327   UNCORRECTIBLE_ERROR,    17,
1328   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1329   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1330   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1331   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1332   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1333   UNCORRECTIBLE_ERROR,    3,
1334   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1335   UNCORRECTIBLE_ERROR,    15,
1336   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1337   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1338   27,                     UNCORRECTIBLE_ERROR,
1339   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1340   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1341   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1342   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1343   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1344   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1345   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1346   32,                     UNCORRECTIBLE_ERROR,
1347   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1348   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1349   9,                      UNCORRECTIBLE_ERROR,
1350   UNCORRECTIBLE_ERROR,    24,
1351   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1352   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1353   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1354   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1355   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1356   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1357   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1358   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1359   UNCORRECTIBLE_ERROR,    1,
1360   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1361   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1362   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1363   11,                     UNCORRECTIBLE_ERROR,
1364   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1365   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1366   20,                     UNCORRECTIBLE_ERROR,
1367   UNCORRECTIBLE_ERROR,    13,
1368   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1369   18,                     UNCORRECTIBLE_ERROR,
1370   4,                      UNCORRECTIBLE_ERROR,
1371   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1372   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1373   16,                     UNCORRECTIBLE_ERROR,
1374   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1375   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1376   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1377   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1378   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1379   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1380   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1381   UNCORRECTIBLE_ERROR,    25,
1382   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1383   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1384   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1385   2,                      UNCORRECTIBLE_ERROR,
1386   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1387   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1388   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1389   14,                     UNCORRECTIBLE_ERROR,
1390   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1391   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1392   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1393   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1394   26,                     UNCORRECTIBLE_ERROR,
1395   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1396   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1397   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1398   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1399   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1400   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1401   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1402   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1403   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1404   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1405   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1406   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1407   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1408   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1409   UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1410 };
1411
1412 /*
1413  * Return an indication of whether there was an error in the cell header
1414  * and, if so, where the error was, if it was correctable.
1415  */
1416 static int
1417 get_header_err(const guint8 *cell_header)
1418 {
1419   register guint8 syndrome;
1420   register int i, err_posn;
1421
1422   syndrome = 0;
1423   for (i = 0;  i < 4;  i++)
1424     syndrome = syndrome_table[syndrome ^ cell_header[i]];
1425   syndrome ^= cell_header[4] ^ COSET_LEADER;
1426
1427   err_posn = err_posn_table [syndrome];
1428
1429   if (err_posn < 0)
1430     return NO_ERROR_DETECTED;
1431   else if (err_posn < 40)
1432     return err_posn;
1433   else
1434     return UNCORRECTIBLE_ERROR;
1435 }
1436
1437 const value_string atm_pt_vals[] = {
1438   { 0, "User data cell, congestion not experienced, SDU-type = 0" },
1439   { 1, "User data cell, congestion not experienced, SDU-type = 1" },
1440   { 2, "User data cell, congestion experienced, SDU-type = 0" },
1441   { 3, "User data cell, congestion experienced, SDU-type = 1" },
1442   { 4, "Segment OAM F5 flow related cell" },
1443   { 5, "End-to-end OAM F5 flow related cell" },
1444   { 6, "VC resource management cell" },
1445   { 0, NULL }
1446 };
1447
1448 /*
1449  * Charles Michael Heard's CRC-10 code, from
1450  *
1451  *      http://www.cell-relay.com/cell-relay/publications/software/CRC/crc10.html
1452  *
1453  * with the CRC table initialized with values computed by
1454  * his "gen_byte_crc10_table()" routine, rather than by calling that
1455  * routine at run time, and with various data type cleanups.
1456  */
1457 static const guint16 byte_crc10_table[256] = {
1458   0x0000, 0x0233, 0x0255, 0x0066, 0x0299, 0x00aa, 0x00cc, 0x02ff,
1459   0x0301, 0x0132, 0x0154, 0x0367, 0x0198, 0x03ab, 0x03cd, 0x01fe,
1460   0x0031, 0x0202, 0x0264, 0x0057, 0x02a8, 0x009b, 0x00fd, 0x02ce,
1461   0x0330, 0x0103, 0x0165, 0x0356, 0x01a9, 0x039a, 0x03fc, 0x01cf,
1462   0x0062, 0x0251, 0x0237, 0x0004, 0x02fb, 0x00c8, 0x00ae, 0x029d,
1463   0x0363, 0x0150, 0x0136, 0x0305, 0x01fa, 0x03c9, 0x03af, 0x019c,
1464   0x0053, 0x0260, 0x0206, 0x0035, 0x02ca, 0x00f9, 0x009f, 0x02ac,
1465   0x0352, 0x0161, 0x0107, 0x0334, 0x01cb, 0x03f8, 0x039e, 0x01ad,
1466   0x00c4, 0x02f7, 0x0291, 0x00a2, 0x025d, 0x006e, 0x0008, 0x023b,
1467   0x03c5, 0x01f6, 0x0190, 0x03a3, 0x015c, 0x036f, 0x0309, 0x013a,
1468   0x00f5, 0x02c6, 0x02a0, 0x0093, 0x026c, 0x005f, 0x0039, 0x020a,
1469   0x03f4, 0x01c7, 0x01a1, 0x0392, 0x016d, 0x035e, 0x0338, 0x010b,
1470   0x00a6, 0x0295, 0x02f3, 0x00c0, 0x023f, 0x000c, 0x006a, 0x0259,
1471   0x03a7, 0x0194, 0x01f2, 0x03c1, 0x013e, 0x030d, 0x036b, 0x0158,
1472   0x0097, 0x02a4, 0x02c2, 0x00f1, 0x020e, 0x003d, 0x005b, 0x0268,
1473   0x0396, 0x01a5, 0x01c3, 0x03f0, 0x010f, 0x033c, 0x035a, 0x0169,
1474   0x0188, 0x03bb, 0x03dd, 0x01ee, 0x0311, 0x0122, 0x0144, 0x0377,
1475   0x0289, 0x00ba, 0x00dc, 0x02ef, 0x0010, 0x0223, 0x0245, 0x0076,
1476   0x01b9, 0x038a, 0x03ec, 0x01df, 0x0320, 0x0113, 0x0175, 0x0346,
1477   0x02b8, 0x008b, 0x00ed, 0x02de, 0x0021, 0x0212, 0x0274, 0x0047,
1478   0x01ea, 0x03d9, 0x03bf, 0x018c, 0x0373, 0x0140, 0x0126, 0x0315,
1479   0x02eb, 0x00d8, 0x00be, 0x028d, 0x0072, 0x0241, 0x0227, 0x0014,
1480   0x01db, 0x03e8, 0x038e, 0x01bd, 0x0342, 0x0171, 0x0117, 0x0324,
1481   0x02da, 0x00e9, 0x008f, 0x02bc, 0x0043, 0x0270, 0x0216, 0x0025,
1482   0x014c, 0x037f, 0x0319, 0x012a, 0x03d5, 0x01e6, 0x0180, 0x03b3,
1483   0x024d, 0x007e, 0x0018, 0x022b, 0x00d4, 0x02e7, 0x0281, 0x00b2,
1484   0x017d, 0x034e, 0x0328, 0x011b, 0x03e4, 0x01d7, 0x01b1, 0x0382,
1485   0x027c, 0x004f, 0x0029, 0x021a, 0x00e5, 0x02d6, 0x02b0, 0x0083,
1486   0x012e, 0x031d, 0x037b, 0x0148, 0x03b7, 0x0184, 0x01e2, 0x03d1,
1487   0x022f, 0x001c, 0x007a, 0x0249, 0x00b6, 0x0285, 0x02e3, 0x00d0,
1488   0x011f, 0x032c, 0x034a, 0x0179, 0x0386, 0x01b5, 0x01d3, 0x03e0,
1489   0x021e, 0x002d, 0x004b, 0x0278, 0x0087, 0x02b4, 0x02d2, 0x00e1,
1490 };
1491
1492 /* update the data block's CRC-10 remainder one byte at a time */
1493 static guint16
1494 update_crc10_by_bytes(guint16 crc10_accum, const guint8 *data_blk_ptr,
1495                       int data_blk_size)
1496 {
1497   register int i;
1498
1499   for (i = 0;  i < data_blk_size; i++) {
1500     crc10_accum = ((crc10_accum << 8) & 0x3ff)
1501       ^ byte_crc10_table[( crc10_accum >> 2) & 0xff]
1502       ^ *data_blk_ptr++;
1503   }
1504   return crc10_accum;
1505 }
1506
1507 static const value_string st_vals[] = {
1508   { 2, "BOM" },
1509   { 0, "COM" },
1510   { 1, "EOM" },
1511   { 3, "SSM" },
1512   { 0, NULL }
1513 };
1514
1515 #define OAM_TYPE_FM     1       /* Fault Management */
1516 #define OAM_TYPE_PM     2       /* Performance Management */
1517 #define OAM_TYPE_AD     8       /* Activation/Deactivation */
1518
1519 static const value_string oam_type_vals[] = {
1520   { OAM_TYPE_FM, "Fault Management" },
1521   { OAM_TYPE_PM, "Performance Management" },
1522   { OAM_TYPE_AD, "Activation/Deactivation" },
1523   { 0,           NULL }
1524 };
1525
1526 static const value_string ft_fm_vals[] = {
1527   { 0, "Alarm Indication Signal" },
1528   { 1, "Far End Receive Failure" },
1529   { 8, "OAM Cell Loopback" },
1530   { 4, "Continuity Check" },
1531   { 0, NULL }
1532 };
1533
1534 static const value_string ft_pm_vals[] = {
1535   { 0, "Forward Monitoring" },
1536   { 1, "Backward Reporting" },
1537   { 2, "Monitoring and Reporting" },
1538   { 0, NULL }
1539 };
1540
1541 static const value_string ft_ad_vals[] = {
1542   { 0, "Performance Monitoring" },
1543   { 1, "Continuity Check" },
1544   { 0, NULL }
1545 };
1546
1547
1548 /*
1549  * Check for OAM cells.
1550  * OAM F4 is VCI 3 or 4 and PT 0X0.
1551  * OAM F5 is PT 10X.
1552  */
1553 gboolean atm_is_oam_cell(const guint16 vci, const guint8 pt)
1554 {
1555   return  (((vci == 3 || vci == 4) && ((pt & 0x5) == 0))
1556            || ((pt & 0x6) == 0x4));
1557 }
1558
1559
1560 static void
1561 dissect_atm_cell(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1562                  proto_tree *atm_tree, guint aal, gboolean nni,
1563                  gboolean crc_stripped)
1564 {
1565   int          offset;
1566   proto_tree   *aal_tree;
1567   proto_item   *ti;
1568   guint8       octet;
1569   int          err;
1570   guint16      vpi;
1571   guint16      vci;
1572   guint8       pt;
1573   guint16      aal3_4_hdr, aal3_4_trlr;
1574   guint16      oam_crc;
1575   gint         length;
1576   guint16      crc10;
1577   tvbuff_t     *next_tvb;
1578   const pwatm_private_data_t * pwpd = pinfo->private_data;
1579
1580   if (NULL == pwpd) {
1581     if (!nni) {
1582       /*
1583        * FF: ITU-T I.361 (Section 2.2) defines the cell header format
1584        * and encoding at UNI reference point as:
1585        *
1586        *  8 7 6 5 4 3 2 1
1587        * +-+-+-+-+-+-+-+-+
1588        * |  GFC  |  VPI  |
1589        * +-+-+-+-+-+-+-+-+
1590        * |  VPI  |  VCI  |
1591        * +-+-+-+-+-+-+-+-+
1592        * |      VCI      |
1593        * +-+-+-+-+-+-+-+-+
1594        * |  VCI  |  PT |C|
1595        * +-+-+-+-+-+-+-+-+
1596        * |   HEC (CRC)   |
1597        * +-+-+-+-+-+-+-+-+
1598        */
1599       octet = tvb_get_guint8(tvb, 0);
1600       proto_tree_add_text(atm_tree, tvb, 0, 1, "GFC: 0x%x", octet >> 4);
1601       vpi = (octet & 0xF) << 4;
1602       octet = tvb_get_guint8(tvb, 1);
1603       vpi |= octet >> 4;
1604       proto_tree_add_uint(atm_tree, hf_atm_vpi, tvb, 0, 2, vpi);
1605     } else {
1606       /*
1607        * FF: ITU-T I.361 (Section 2.3) defines the cell header format
1608        * and encoding at NNI reference point as:
1609        *
1610        *  8 7 6 5 4 3 2 1
1611        * +-+-+-+-+-+-+-+-+
1612        * |      VPI      |
1613        * +-+-+-+-+-+-+-+-+
1614        * |  VPI  |  VCI  |
1615        * +-+-+-+-+-+-+-+-+
1616        * |      VCI      |
1617        * +-+-+-+-+-+-+-+-+
1618        * |  VCI  |  PT |C|
1619        * +-+-+-+-+-+-+-+-+
1620        * |   HEC (CRC)   |
1621        * +-+-+-+-+-+-+-+-+
1622        */
1623       octet = tvb_get_guint8(tvb, 0);
1624       vpi = octet << 4;
1625       octet = tvb_get_guint8(tvb, 1);
1626       vpi |= (octet & 0xF0) >> 4;
1627       proto_tree_add_uint(atm_tree, hf_atm_vpi, tvb, 0, 2, vpi);
1628     }
1629
1630     vci = (octet & 0x0F) << 12;
1631     octet = tvb_get_guint8(tvb, 2);
1632     vci |= octet << 4;
1633     octet = tvb_get_guint8(tvb, 3);
1634     vci |= octet >> 4;
1635     proto_tree_add_uint(atm_tree, hf_atm_vci, tvb, 1, 3, vci);
1636     pt = (octet >> 1) & 0x7;
1637     proto_tree_add_text(atm_tree, tvb, 3, 1, "Payload Type: %s",
1638                         val_to_str(pt, atm_pt_vals, "Unknown (%u)"));
1639     proto_tree_add_text(atm_tree, tvb, 3, 1, "Cell Loss Priority: %s",
1640                         (octet & 0x01) ? "Low priority" : "High priority");
1641
1642     if (!crc_stripped) {
1643       /*
1644        * FF: parse the Header Error Check (HEC).
1645        */
1646       ti = proto_tree_add_text(atm_tree, tvb, 4, 1,
1647                                "Header Error Check: 0x%02x",
1648                                tvb_get_guint8(tvb, 4));
1649       err = get_header_err(tvb_get_ptr(tvb, 0, 5));
1650       if (err == NO_ERROR_DETECTED)
1651         proto_item_append_text(ti, " (correct)");
1652       else if (err == UNCORRECTIBLE_ERROR)
1653         proto_item_append_text(ti, " (uncorrectable error)");
1654       else
1655         proto_item_append_text(ti, " (error in bit %d)", err);
1656       offset = 5;
1657     } else {
1658       /*
1659        * FF: in some encapsulation modes (e.g. RFC 4717, ATM N-to-One
1660        * Cell Mode) the Header Error Check (HEC) field is stripped.
1661        * So we do nothing here.
1662        */
1663       offset = 4;
1664     }
1665   }
1666   else
1667   {
1668     offset = 0; /* For PWs. Header is decoded by PW dissector.*/
1669     pwpd = pinfo->private_data;
1670     vpi = pwpd->vpi;
1671     vci = pwpd->vci;
1672     pt  = pwpd->pti;
1673   }
1674
1675   /*
1676    * Check for OAM cells.
1677    * XXX - do this for all AAL values, overriding whatever information
1678    * Wiretap got from the file?
1679    */
1680   if (aal == AAL_USER) {
1681     if (atm_is_oam_cell(vci,pt)) {
1682       aal = AAL_OAMCELL;
1683     }
1684   }
1685
1686   switch (aal) {
1687
1688   case AAL_1:
1689     col_set_str(pinfo->cinfo, COL_PROTOCOL, "AAL1");
1690     col_clear(pinfo->cinfo, COL_INFO);
1691     ti = proto_tree_add_item(tree, proto_aal1, tvb, offset, -1, ENC_NA);
1692     aal_tree = proto_item_add_subtree(ti, ett_aal1);
1693     octet = tvb_get_guint8(tvb, offset);
1694     proto_tree_add_text(aal_tree, tvb, offset, 1, "CSI: %u", octet >> 7);
1695     proto_tree_add_text(aal_tree, tvb, offset, 1, "Sequence Count: %u",
1696                         (octet >> 4) & 0x7);
1697     col_add_fstr(pinfo->cinfo, COL_INFO, "Sequence count = %u",
1698                  (octet >> 4) & 0x7);
1699     proto_tree_add_text(aal_tree, tvb, offset, 1, "CRC: 0x%x",
1700                         (octet >> 1) & 0x7);
1701     proto_tree_add_text(aal_tree, tvb, offset, 1, "Parity: %u",
1702                         octet & 0x1);
1703     offset++;
1704
1705     proto_tree_add_text(aal_tree, tvb, offset, 47, "Payload");
1706     break;
1707
1708   case AAL_3_4:
1709     /*
1710      * XXX - or should this be the CS PDU?
1711      */
1712     col_set_str(pinfo->cinfo, COL_PROTOCOL, "AAL3/4");
1713     col_clear(pinfo->cinfo, COL_INFO);
1714     ti = proto_tree_add_item(tree, proto_aal3_4, tvb, offset, -1, ENC_NA);
1715     aal_tree = proto_item_add_subtree(ti, ett_aal3_4);
1716     aal3_4_hdr = tvb_get_ntohs(tvb, offset);
1717     col_add_fstr(pinfo->cinfo, COL_INFO, "%s, sequence number = %u",
1718                  val_to_str(aal3_4_hdr >> 14, st_vals, "Unknown (%u)"),
1719                  (aal3_4_hdr >> 10) & 0xF);
1720     proto_tree_add_text(aal_tree, tvb, offset, 2, "Segment Type: %s",
1721                         val_to_str(aal3_4_hdr >> 14, st_vals, "Unknown (%u)"));
1722     proto_tree_add_text(aal_tree, tvb, offset, 2, "Sequence Number: %u",
1723                         (aal3_4_hdr >> 10) & 0xF);
1724     proto_tree_add_text(aal_tree, tvb, offset, 2, "Multiplex ID: %u",
1725                         aal3_4_hdr & 0x3FF);
1726     offset += 2;
1727
1728     proto_tree_add_text(aal_tree, tvb, offset, 44, "Information");
1729     offset += 44;
1730
1731     aal3_4_trlr = tvb_get_ntohs(tvb, offset);
1732     proto_tree_add_text(aal_tree, tvb, offset, 2, "Length Indicator: %u",
1733                         (aal3_4_trlr >> 10) & 0x3F);
1734     length = tvb_length_remaining(tvb, 5);
1735     crc10 = update_crc10_by_bytes(0, tvb_get_ptr(tvb, 5, length),
1736                                   length);
1737     proto_tree_add_text(aal_tree, tvb, offset, 2, "CRC: 0x%03x (%s)",
1738                         aal3_4_trlr & 0x3FF,
1739                         (crc10 == 0) ? "correct" : "incorrect");
1740     break;
1741
1742   case AAL_OAMCELL:
1743     if (NULL == pwpd || pwpd->enable_fill_columns_by_atm_dissector)
1744     {
1745       col_set_str(pinfo->cinfo, COL_PROTOCOL, "OAM AAL");
1746       col_clear(pinfo->cinfo, COL_INFO);
1747     }
1748     ti = proto_tree_add_item(tree, proto_oamaal, tvb, offset, -1, ENC_NA);
1749     aal_tree = proto_item_add_subtree(ti, ett_oamaal);
1750     octet = tvb_get_guint8(tvb, offset);
1751     if (NULL == pwpd || pwpd->enable_fill_columns_by_atm_dissector)
1752     {
1753       col_add_fstr(pinfo->cinfo, COL_INFO, "%s",
1754                    val_to_str(octet >> 4, oam_type_vals, "Unknown (%u)"));
1755     }
1756     proto_tree_add_text(aal_tree, tvb, offset, 1, "OAM Type: %s",
1757                         val_to_str(octet >> 4, oam_type_vals, "Unknown (%u)"));
1758     switch (octet >> 4) {
1759
1760     case OAM_TYPE_FM:
1761       proto_tree_add_text(aal_tree, tvb, offset, 1, "Function Type: %s",
1762                           val_to_str(octet & 0x0F, ft_fm_vals, "Unknown (%u)"));
1763       break;
1764
1765     case OAM_TYPE_PM:
1766       proto_tree_add_text(aal_tree, tvb, offset, 1, "Function Type: %s",
1767                           val_to_str(octet & 0x0F, ft_pm_vals, "Unknown (%u)"));
1768       break;
1769
1770     case OAM_TYPE_AD:
1771       proto_tree_add_text(aal_tree, tvb, offset, 1, "Function Type: %s",
1772                           val_to_str(octet & 0x0F, ft_ad_vals, "Unknown (%u)"));
1773       break;
1774
1775     default:
1776       proto_tree_add_text(aal_tree, tvb, offset, 1, "Function Type: %u",
1777                           octet & 0x0F);
1778       break;
1779     }
1780     offset += 1;
1781
1782     proto_tree_add_text(aal_tree, tvb, offset, 45, "Function-specific information");
1783     offset += 45;
1784
1785     length = tvb_length_remaining(tvb, 5);
1786     crc10 = update_crc10_by_bytes(0, tvb_get_ptr(tvb, 5, length),
1787                                   length);
1788     oam_crc = tvb_get_ntohs(tvb, offset);
1789     proto_tree_add_text(aal_tree, tvb, offset, 2, "CRC-10: 0x%03x (%s)",
1790                         oam_crc & 0x3FF,
1791                         (crc10 == 0) ? "correct" : "incorrect");
1792     break;
1793
1794   default:
1795     next_tvb = tvb_new_subset_remaining(tvb, offset);
1796     call_dissector(data_handle, next_tvb, pinfo, tree);
1797     break;
1798   }
1799 }
1800
1801 static void
1802 dissect_atm_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1803     gboolean truncated)
1804 {
1805   proto_tree   *atm_tree = NULL;
1806   proto_item   *atm_ti = NULL;
1807   gboolean     pseudowire_mode = (NULL != pinfo->private_data);
1808
1809   if ( pinfo->pseudo_header->atm.aal == AAL_5 &&
1810        pinfo->pseudo_header->atm.type == TRAF_LANE &&
1811        dissect_lanesscop ) {
1812     pinfo->pseudo_header->atm.aal = AAL_SIGNALLING;
1813   }
1814
1815   col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATM");
1816
1817   if (!pseudowire_mode) {
1818     switch (pinfo->pseudo_header->atm.channel) {
1819
1820     case 0:
1821       /* Traffic from DTE to DCE. */
1822       col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DCE");
1823       col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DTE");
1824       break;
1825
1826     case 1:
1827       /* Traffic from DCE to DTE. */
1828       col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DTE");
1829       col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DCE");
1830       break;
1831     }
1832   }
1833
1834   if (pinfo->pseudo_header->atm.aal == AAL_5) {
1835     col_add_fstr(pinfo->cinfo, COL_INFO, "AAL5 %s",
1836                  val_to_str(pinfo->pseudo_header->atm.type, aal5_hltype_vals,
1837                             "Unknown traffic type (%u)"));
1838   } else {
1839     col_add_str(pinfo->cinfo, COL_INFO,
1840                 val_to_str(pinfo->pseudo_header->atm.aal, aal_vals,
1841                            "Unknown AAL (%u)"));
1842   }
1843
1844   if (tree) {
1845     atm_ti = proto_tree_add_item(tree, proto_atm, tvb, 0, -1, ENC_NA);
1846     atm_tree = proto_item_add_subtree(atm_ti, ett_atm);
1847
1848     if (!pseudowire_mode) {
1849       switch (pinfo->pseudo_header->atm.channel) {
1850
1851       case 0:
1852         /* Traffic from DTE to DCE. */
1853         proto_tree_add_text(atm_tree, tvb, 0, 0, "Channel: DTE->DCE");
1854         break;
1855
1856       case 1:
1857         /* Traffic from DCE to DTE. */
1858         proto_tree_add_text(atm_tree, tvb, 0, 0, "Channel: DCE->DTE");
1859         break;
1860
1861       default:
1862         /* Sniffers shouldn't provide anything other than 0 or 1. */
1863         proto_tree_add_text(atm_tree, tvb, 0, 0, "Channel: %u",
1864                             pinfo->pseudo_header->atm.channel);
1865         break;
1866       }
1867     }
1868
1869     proto_tree_add_uint_format_value(atm_tree, hf_atm_aal, tvb, 0, 0,
1870                                      pinfo->pseudo_header->atm.aal,
1871                                      "%s",
1872                                      val_to_str(pinfo->pseudo_header->atm.aal, aal_vals,
1873                                                 "Unknown AAL (%u)"));
1874   }
1875   if (pinfo->pseudo_header->atm.flags & ATM_RAW_CELL) {
1876     /* This is a single cell, with the cell header at the beginning. */
1877     if (pinfo->pseudo_header->atm.flags & ATM_NO_HEC) {
1878       proto_item_set_len(atm_ti, 4);
1879     } else {
1880       proto_item_set_len(atm_ti, 5);
1881     }
1882     dissect_atm_cell(tvb, pinfo, tree, atm_tree,
1883                      pinfo->pseudo_header->atm.aal, FALSE,
1884                      pinfo->pseudo_header->atm.flags & ATM_NO_HEC);
1885   } else {
1886     /* This is a reassembled PDU. */
1887     dissect_reassembled_pdu(tvb, pinfo, tree, atm_tree, atm_ti, truncated);
1888   }
1889 }
1890
1891 static void
1892 dissect_atm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1893 {
1894   dissect_atm_common(tvb, pinfo, tree, TRUE);
1895 }
1896
1897 static void
1898 dissect_atm_untruncated(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1899 {
1900   dissect_atm_common(tvb, pinfo, tree, ENC_BIG_ENDIAN);
1901 }
1902
1903 static void
1904 dissect_atm_oam_cell(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1905 {
1906   proto_tree   *atm_tree = NULL;
1907   proto_item   *atm_ti = NULL;
1908   gboolean     pseudowire_mode = (NULL != pinfo->private_data);
1909
1910   col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATM");
1911
1912   if (!pseudowire_mode) {
1913     if (tree) {
1914       atm_ti = proto_tree_add_protocol_format(tree, proto_atm, tvb, 0, 0, "ATM");
1915       atm_tree = proto_item_add_subtree(atm_ti, ett_atm);
1916     }
1917   }
1918
1919   dissect_atm_cell(tvb, pinfo, tree, atm_tree, AAL_OAMCELL, FALSE, ENC_BIG_ENDIAN);
1920 }
1921
1922
1923 void
1924 proto_register_atm(void)
1925 {
1926   static hf_register_info hf[] = {
1927     { &hf_atm_aal,
1928       { "AAL",          "atm.aal", FT_UINT8, BASE_DEC, VALS(aal_vals), 0x0,
1929         NULL, HFILL }},
1930
1931     { &hf_atm_vpi,
1932       { "VPI",          "atm.vpi", FT_UINT8, BASE_DEC, NULL, 0x0,
1933         NULL, HFILL }},
1934
1935     { &hf_atm_vci,
1936       { "VCI",          "atm.vci", FT_UINT16, BASE_DEC, NULL, 0x0,
1937         NULL, HFILL }},
1938
1939     { &hf_atm_cid,
1940       { "CID",          "atm.cid", FT_UINT8, BASE_DEC, NULL, 0x0,
1941         NULL, HFILL }},
1942
1943   };
1944   static gint *ett[] = {
1945     &ett_atm,
1946     &ett_ilmi,
1947     &ett_aal1,
1948     &ett_aal3_4,
1949     &ett_oamaal,
1950     &ett_atm_lane,
1951     &ett_atm_lane_lc_lan_dest,
1952     &ett_atm_lane_lc_lan_dest_rd,
1953     &ett_atm_lane_lc_flags,
1954     &ett_atm_lane_lc_tlv,
1955   };
1956
1957   static enum_val_t unknown_aal2_options[] = {
1958     { "raw",     "Raw data", TRAF_UNKNOWN },
1959     { "umts_fp", "UMTS FP",  TRAF_UMTS_FP },
1960     { NULL, NULL, 0 }
1961   };
1962
1963   module_t *atm_module;
1964
1965   proto_atm = proto_register_protocol("Asynchronous Transfer Mode", "ATM", "atm");
1966   proto_aal1 = proto_register_protocol("ATM AAL1", "AAL1", "aal1");
1967   proto_aal3_4 = proto_register_protocol("ATM AAL3/4", "AAL3/4", "aal3_4");
1968   proto_oamaal = proto_register_protocol("ATM OAM AAL", "OAM AAL", "oamaal");
1969   proto_register_field_array(proto_atm, hf, array_length(hf));
1970   proto_register_subtree_array(ett, array_length(ett));
1971
1972   proto_ilmi = proto_register_protocol("ILMI", "ILMI", "ilmi");
1973
1974   register_dissector("ilmi", dissect_ilmi, proto_ilmi);
1975
1976   proto_atm_lane = proto_register_protocol("ATM LAN Emulation",
1977                                            "ATM LANE", "lane");
1978
1979   register_dissector("lane", dissect_lane, proto_atm_lane);
1980   register_dissector("atm_untruncated", dissect_atm_untruncated, proto_atm);
1981   register_dissector("atm_truncated", dissect_atm, proto_atm);
1982   register_dissector("atm_oam_cell", dissect_atm_oam_cell, proto_oamaal);
1983
1984   atm_module = prefs_register_protocol ( proto_atm, NULL );
1985   prefs_register_bool_preference ( atm_module, "dissect_lane_as_sscop", "Dissect LANE as SSCOP",
1986                                    "Autodection between LANE and SSCOP is hard. As default LANE is preferred",
1987                                    &dissect_lanesscop);
1988   prefs_register_enum_preference ( atm_module, "unknown_aal2_type",
1989                                    "Decode unknown AAL2 traffic as",
1990                                    "Type used to dissect unknown AAL2 traffic",
1991                                    &unknown_aal2_type, unknown_aal2_options, ENC_BIG_ENDIAN);
1992
1993 }
1994
1995 void
1996 proto_reg_handoff_atm(void)
1997 {
1998   dissector_handle_t atm_handle, atm_untruncated_handle;
1999
2000   /*
2001    * Get handles for the Ethernet, Token Ring, Frame Relay, LLC,
2002    * SSCOP, LANE, and ILMI dissectors.
2003    */
2004   eth_withoutfcs_handle = find_dissector("eth_withoutfcs");
2005   tr_handle = find_dissector("tr");
2006   fr_handle = find_dissector("fr");
2007   llc_handle = find_dissector("llc");
2008   sscop_handle = find_dissector("sscop");
2009   lane_handle = find_dissector("lane");
2010   ilmi_handle = find_dissector("ilmi");
2011   ppp_handle = find_dissector("ppp");
2012   eth_handle = find_dissector("eth");
2013   ip_handle = find_dissector("ip");
2014   data_handle = find_dissector("data");
2015   fp_handle = find_dissector("fp");
2016   gprs_ns_handle = find_dissector("gprs_ns");
2017
2018   atm_handle = create_dissector_handle(dissect_atm, proto_atm);
2019   dissector_add_uint("wtap_encap", WTAP_ENCAP_ATM_PDUS, atm_handle);
2020
2021   atm_untruncated_handle = create_dissector_handle(dissect_atm_untruncated,
2022                                                    proto_atm);
2023   dissector_add_uint("wtap_encap", WTAP_ENCAP_ATM_PDUS_UNTRUNCATED,
2024                 atm_untruncated_handle);
2025 }