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