Don't guard col_set_str (COL_INFO) 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   col_set_str(pinfo->cinfo, COL_INFO, "LE Control");
491
492   if (tree) {
493     ti = proto_tree_add_protocol_format(tree, proto_atm_lane, tvb, offset, 108, "ATM LANE");
494     lane_tree = proto_item_add_subtree(ti, ett_atm_lane);
495
496     proto_tree_add_text(lane_tree, tvb, offset, 2, "Marker: 0x%04X",
497                         tvb_get_ntohs(tvb, offset));
498   }
499   offset += 2;
500
501   if (tree) {
502     proto_tree_add_text(lane_tree, tvb, offset, 1, "Protocol: 0x%02X",
503                         tvb_get_guint8(tvb, offset));
504   }
505   offset += 1;
506
507   if (tree) {
508     proto_tree_add_text(lane_tree, tvb, offset, 1, "Version: 0x%02X",
509                         tvb_get_guint8(tvb, offset));
510   }
511   offset += 1;
512
513   opcode = tvb_get_ntohs(tvb, offset);
514   if (check_col(pinfo->cinfo, COL_INFO)) {
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(tvb, 2, -1, -1);
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(tvb, 2, -1, -1);
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(tvb, 0, -1, -1);
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, FALSE);
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         { 0,              NULL }
731 };
732
733 /* Traffic subtypes for VC multiplexed traffic */
734 static const value_string vcmx_type_vals[] = {
735         { TRAF_ST_UNKNOWN,        "Unknown VC multiplexed traffic type" },
736         { TRAF_ST_VCMX_802_3_FCS, "802.3 FCS" },
737         { TRAF_ST_VCMX_802_4_FCS, "802.4 FCS" },
738         { TRAF_ST_VCMX_802_5_FCS, "802.5 FCS" },
739         { TRAF_ST_VCMX_FDDI_FCS,  "FDDI FCS" },
740         { TRAF_ST_VCMX_802_6_FCS, "802.6 FCS" },
741         { TRAF_ST_VCMX_802_3,     "802.3" },
742         { TRAF_ST_VCMX_802_4,     "802.4" },
743         { TRAF_ST_VCMX_802_5,     "802.5" },
744         { TRAF_ST_VCMX_FDDI,      "FDDI" },
745         { TRAF_ST_VCMX_802_6,     "802.6" },
746         { TRAF_ST_VCMX_FRAGMENTS, "Fragments" },
747         { TRAF_ST_VCMX_BPDU,      "BPDU" },
748         { 0,                   NULL }
749 };
750
751 /* Traffic subtypes for LANE traffic */
752 static const value_string lane_type_vals[] = {
753         { TRAF_ST_UNKNOWN,       "Unknown LANE traffic type" },
754         { TRAF_ST_LANE_LE_CTRL,  "LE Control" },
755         { TRAF_ST_LANE_802_3,    "802.3" },
756         { TRAF_ST_LANE_802_5,    "802.5" },
757         { TRAF_ST_LANE_802_3_MC, "802.3 multicast" },
758         { TRAF_ST_LANE_802_5_MC, "802.5 multicast" },
759         { 0,                     NULL }
760 };
761
762 /* Traffic subtypes for Ipsilon traffic */
763 static const value_string ipsilon_type_vals[] = {
764         { TRAF_ST_UNKNOWN,     "Unknown Ipsilon traffic type" },
765         { TRAF_ST_IPSILON_FT0, "Flow type 0" },
766         { TRAF_ST_IPSILON_FT1, "Flow type 1" },
767         { TRAF_ST_IPSILON_FT2, "Flow type 2" },
768         { 0,                NULL }
769 };
770
771 void
772 capture_atm(const union wtap_pseudo_header *pseudo_header, const guchar *pd,
773     int len, packet_counts *ld)
774 {
775   if (pseudo_header->atm.aal == AAL_5) {
776     switch (pseudo_header->atm.type) {
777
778     case TRAF_LLCMX:
779       /* Dissect as WTAP_ENCAP_ATM_RFC1483 */
780       /* The ATM iptrace capture that we have shows LLC at this point,
781        * so that's what I'm calling */
782       capture_llc(pd, 0, len, ld);
783       break;
784
785     case TRAF_LANE:
786       capture_lane(pseudo_header, pd, len, ld);
787       break;
788
789     default:
790       ld->other++;
791       break;
792     }
793   } else
794     ld->other++;
795 }
796
797 /*
798  * Charles Michael Heard's CRC-32 code, from
799  *
800  *      http://www.cell-relay.com/cell-relay/publications/software/CRC/32bitCRC.c.html
801  *
802  * with the CRC table initialized with values computed by
803  * his "gen_crc_table()" routine, rather than by calling that routine
804  * at run time, and with various data type cleanups.
805  */
806
807 /* crc32h.c -- package to compute 32-bit CRC one byte at a time using   */
808 /*             the high-bit first (Big-Endian) bit ordering convention  */
809 /*                                                                      */
810 /* Synopsis:                                                            */
811 /*  gen_crc_table() -- generates a 256-word table containing all CRC    */
812 /*                     remainders for every possible 8-bit byte.  It    */
813 /*                     must be executed (once) before any CRC updates.  */
814 /*                                                                      */
815 /*  unsigned update_crc(crc_accum, data_blk_ptr, data_blk_size)         */
816 /*           unsigned crc_accum; char *data_blk_ptr; int data_blk_size; */
817 /*           Returns the updated value of the CRC accumulator after     */
818 /*           processing each byte in the addressed block of data.       */
819 /*                                                                      */
820 /*  It is assumed that an unsigned long is at least 32 bits wide and    */
821 /*  that the predefined type char occupies one 8-bit byte of storage.   */
822 /*                                                                      */
823 /*  The generator polynomial used for this version of the package is    */
824 /*  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 */
825 /*  as specified in the Autodin/Ethernet/ADCCP protocol standards.      */
826 /*  Other degree 32 polynomials may be substituted by re-defining the   */
827 /*  symbol POLYNOMIAL below.  Lower degree polynomials must first be    */
828 /*  multiplied by an appropriate power of x.  The representation used   */
829 /*  is that the coefficient of x^0 is stored in the LSB of the 32-bit   */
830 /*  word and the coefficient of x^31 is stored in the most significant  */
831 /*  bit.  The CRC is to be appended to the data most significant byte   */
832 /*  first.  For those protocols in which bytes are transmitted MSB      */
833 /*  first and in the same order as they are encountered in the block    */
834 /*  this convention results in the CRC remainder being transmitted with */
835 /*  the coefficient of x^31 first and with that of x^0 last (just as    */
836 /*  would be done by a hardware shift register mechanization).          */
837 /*                                                                      */
838 /*  The table lookup technique was adapted from the algorithm described */
839 /*  by Avram Perez, Byte-wise CRC Calculations, IEEE Micro 3, 40 (1983).*/
840
841 static const guint32 crc_table[256] = {
842         0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
843         0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
844         0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
845         0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
846         0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,
847         0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
848         0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011,
849         0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
850         0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
851         0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
852         0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,
853         0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
854         0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49,
855         0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
856         0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
857         0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
858         0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,
859         0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
860         0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
861         0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
862         0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
863         0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
864         0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,
865         0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
866         0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e,
867         0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
868         0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
869         0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
870         0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
871         0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
872         0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686,
873         0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
874         0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
875         0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
876         0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,
877         0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
878         0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47,
879         0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
880         0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
881         0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
882         0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,
883         0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
884         0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f,
885         0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
886         0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
887         0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
888         0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,
889         0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
890         0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
891         0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
892         0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
893         0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
894         0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
895         0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
896         0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,
897         0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
898         0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
899         0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
900         0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
901         0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
902         0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,
903         0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
904         0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
905         0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4,
906 };
907
908 static guint32
909 update_crc(guint32 crc_accum, const guint8 *data_blk_ptr, int data_blk_size)
910 {
911   register int i, j;
912
913   /* update the CRC on the data block one byte at a time */
914   for (j = 0; j < data_blk_size;  j++) {
915     i = ( (int) ( crc_accum >> 24) ^ *data_blk_ptr++ ) & 0xff;
916     crc_accum = ( crc_accum << 8 ) ^ crc_table[i];
917   }
918   return crc_accum;
919 }
920
921 static void
922 dissect_reassembled_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
923     proto_item *atm_ti,
924     proto_tree *atm_tree, gboolean truncated)
925 {
926   guint        length, reported_length;
927   guint16      aal5_length;
928   int          pad_length;
929   tvbuff_t     *next_tvb;
930   guint32      crc;
931   guint32      calc_crc;
932   /* 
933    * ATM dissector is used as "sub-dissector" for ATM pseudowires.
934    * In such cases, pinfo->private_data is used to pass info from/to 
935    * PW dissector to ATM dissector. For decoding normal ATM traffic 
936    * private_data should be NULL.
937    */
938   gboolean     pseudowire_mode = (NULL != pinfo->private_data);
939
940   /*
941    * This is reassembled traffic, so the cell headers are missing;
942    * show the traffic type for AAL5 traffic, and the VPI and VCI,
943    * from the pseudo-header.
944    */
945   if (pinfo->pseudo_header->atm.aal == AAL_5) {
946     proto_tree_add_text(atm_tree, tvb, 0, 0, "Traffic type: %s",
947                 val_to_str(pinfo->pseudo_header->atm.type, aal5_hltype_vals,
948                 "Unknown AAL5 traffic type (%u)"));
949     switch (pinfo->pseudo_header->atm.type) {
950
951     case TRAF_VCMX:
952       proto_tree_add_text(atm_tree, tvb, 0, 0, "VC multiplexed traffic type: %s",
953                 val_to_str(pinfo->pseudo_header->atm.subtype,
954                         vcmx_type_vals, "Unknown VCMX traffic type (%u)"));
955       break;
956
957     case TRAF_LANE:
958       proto_tree_add_text(atm_tree, tvb, 0, 0, "LANE traffic type: %s",
959                 val_to_str(pinfo->pseudo_header->atm.subtype,
960                         lane_type_vals, "Unknown LANE traffic type (%u)"));
961       break;
962
963     case TRAF_IPSILON:
964       proto_tree_add_text(atm_tree, tvb, 0, 0, "Ipsilon traffic type: %s",
965                 val_to_str(pinfo->pseudo_header->atm.subtype,
966                         ipsilon_type_vals, "Unknown Ipsilon traffic type (%u)"));
967       break;
968     }
969   }
970   if (!pseudowire_mode) {
971     proto_tree_add_uint(atm_tree, hf_atm_vpi, tvb, 0, 0,
972                 pinfo->pseudo_header->atm.vpi);
973     proto_tree_add_uint(atm_tree, hf_atm_vci, tvb, 0, 0,
974                 pinfo->pseudo_header->atm.vci);
975
976     /* Also show vpi/vci in info column */
977     if (check_col(pinfo->cinfo, COL_INFO))
978     {
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
985   next_tvb = tvb;
986   if (truncated) {
987     /*
988      * The packet data does not include stuff such as the AAL5
989      * trailer.
990      */
991     if (pinfo->pseudo_header->atm.cells != 0) {
992       /*
993        * If the cell count is 0, assume it means we don't know how
994        * many cells it was.
995        *
996        * XXX - also assume it means we don't know what was in the AAL5
997        * trailer.  We may, however, find some capture program that can
998        * give us the AAL5 trailer information but not the cell count,
999        * in which case we need some other way of indicating whether we
1000        * have the AAL5 trailer information.
1001        */
1002       if (tree) {
1003         proto_tree_add_text(atm_tree, tvb, 0, 0, "Cells: %u",
1004                 pinfo->pseudo_header->atm.cells);
1005         proto_tree_add_text(atm_tree, tvb, 0, 0, "AAL5 UU: 0x%02x",
1006                 pinfo->pseudo_header->atm.aal5t_u2u >> 8);
1007         proto_tree_add_text(atm_tree, tvb, 0, 0, "AAL5 CPI: 0x%02x",
1008                 pinfo->pseudo_header->atm.aal5t_u2u & 0xFF);
1009         proto_tree_add_text(atm_tree, tvb, 0, 0, "AAL5 len: %u",
1010                 pinfo->pseudo_header->atm.aal5t_len);
1011         proto_tree_add_text(atm_tree, tvb, 0, 0, "AAL5 CRC: 0x%08X",
1012                 pinfo->pseudo_header->atm.aal5t_chksum);
1013       }
1014     }
1015   } else {
1016     /*
1017      * The packet data includes stuff such as the AAL5 trailer, if
1018      * it wasn't cut off by the snapshot length.
1019      * Decode the trailer, if present, and then chop it off.
1020      */
1021     length = tvb_length(tvb);
1022     reported_length = tvb_reported_length(tvb);
1023     if ((reported_length % 48) == 0) {
1024       /*
1025        * Reported length is a multiple of 48, so we can presumably
1026        * divide it by 48 to get the number of cells.
1027        */
1028       proto_tree_add_text(atm_tree, tvb, 0, 0, "Cells: %u",
1029                 reported_length/48);
1030     }
1031     if ((pinfo->pseudo_header->atm.aal == AAL_5 ||
1032         pinfo->pseudo_header->atm.aal == AAL_SIGNALLING) &&
1033         length >= reported_length) {
1034       /*
1035        * XXX - what if the packet is truncated?  Can that happen?
1036        * What if you capture with Windows Sniffer on an ATM link
1037        * and tell it not to save the entire packet?  What happens
1038        * to the trailer?
1039        */
1040       aal5_length = tvb_get_ntohs(tvb, length - 6);
1041
1042       /*
1043        * Check for sanity in the AAL5 length.  It must be > 0
1044        * and must be less than the amount of space left after
1045        * we remove the trailer.
1046        *
1047        * If it's not sane, assume we don't have a trailer.
1048        */
1049       if (aal5_length > 0 && aal5_length <= length - 8) {
1050         /*
1051          * How much padding is there?
1052          */
1053         pad_length = length - aal5_length - 8;
1054
1055         /*
1056          * There is no reason for more than 47 bytes of padding.
1057          * The most padding you can have would be 7 bytes at the
1058          * end of the next-to-last cell (8 bytes after the end of
1059          * the data means you can fit the trailer in that cell),
1060          * plus 40 bytes in the last cell (with the last 8 bytes
1061          * being padding).
1062          *
1063          * If there's more than 47 bytes of padding, assume we don't
1064          * have a trailer.
1065          */
1066         if (pad_length <= 47) {
1067           if (tree) {
1068             if (pad_length > 0) {
1069               proto_tree_add_text(atm_tree, tvb, aal5_length, pad_length,
1070                                   "Padding");
1071             }
1072             proto_tree_add_text(atm_tree, tvb, length - 8, 1, "AAL5 UU: 0x%02x",
1073                                 tvb_get_guint8(tvb, length - 8));
1074             proto_tree_add_text(atm_tree, tvb, length - 7, 1, "AAL5 CPI: 0x%02x",
1075                                 tvb_get_guint8(tvb, length - 7));
1076             proto_tree_add_text(atm_tree, tvb, length - 6, 2, "AAL5 len: %u",
1077                                 aal5_length);
1078             crc = tvb_get_ntohl(tvb, length - 4);
1079             calc_crc = update_crc(0xFFFFFFFF, tvb_get_ptr(tvb, 0, length),
1080                                   length);
1081             proto_tree_add_text(atm_tree, tvb, length - 4, 4,
1082                                 "AAL5 CRC: 0x%08X (%s)", crc,
1083                                 (calc_crc == 0xC704DD7B) ? "correct" : "incorrect");
1084           }
1085           next_tvb = tvb_new_subset(tvb, 0, aal5_length, aal5_length);
1086         }
1087       }
1088     }
1089   }
1090
1091   switch (pinfo->pseudo_header->atm.aal) {
1092
1093   case AAL_SIGNALLING:
1094     call_dissector(sscop_handle, next_tvb, pinfo, tree);
1095     break;
1096
1097   case AAL_5:
1098     switch (pinfo->pseudo_header->atm.type) {
1099
1100     case TRAF_FR:
1101       call_dissector(fr_handle, next_tvb, pinfo, tree);
1102       break;
1103
1104     case TRAF_LLCMX:
1105       call_dissector(llc_handle, next_tvb, pinfo, tree);
1106       break;
1107
1108     case TRAF_LANE:
1109       call_dissector(lane_handle, next_tvb, pinfo, tree);
1110       break;
1111
1112     case TRAF_ILMI:
1113       call_dissector(ilmi_handle, next_tvb, pinfo, tree);
1114       break;
1115
1116     default:
1117       {
1118         gboolean decoded = FALSE;
1119
1120         if (tvb_length(next_tvb) > 7) /* sizeof(octet) */
1121         {
1122             guint8 octet[8];
1123             tvb_memcpy(next_tvb, octet, 0, sizeof(octet)); 
1124
1125             decoded = TRUE;
1126             if (octet[0] == 0xaa
1127              && octet[1] == 0xaa
1128              && octet[2] == 0x03) /* LLC SNAP as per RFC2684 */
1129             {
1130                 call_dissector(llc_handle, next_tvb, pinfo, tree);
1131             }
1132             else if ((pntohs(octet) & 0xff) == PPP_IP)
1133             {
1134                 call_dissector(ppp_handle, next_tvb, pinfo, tree);
1135             }
1136             else if (pntohs(octet) == 0x00)
1137             {
1138                 /* assume vc muxed bridged ethernet */
1139                 proto_tree_add_text(tree, tvb, 0, 2, "Pad: 0x0000");
1140                 next_tvb = tvb_new_subset(tvb, 2, -1, -1);
1141                 call_dissector(eth_handle, next_tvb, pinfo, tree);
1142             }
1143             else if (octet[2] == 0x03    && /* NLPID */
1144                     ((octet[3] == 0xcc   || /* IPv4  */
1145                       octet[3] == 0x8e)  || /* IPv6  */
1146                      (octet[3] == 0x00   && /* Eth   */
1147                       octet[4] == 0x80)))   /* Eth   */
1148             {
1149                 /* assume network interworking with FR 2 byte header */
1150                 call_dissector(fr_handle, next_tvb, pinfo, tree);
1151             }
1152             else if (octet[4] == 0x03    && /* NLPID */
1153                     ((octet[5] == 0xcc   || /* IPv4  */
1154                       octet[5] == 0x8e)  || /* IPv6  */
1155                      (octet[5] == 0x00   && /* Eth   */
1156                       octet[6] == 0x80)))   /* Eth   */
1157             {
1158                 /* assume network interworking with FR 4 byte header */
1159                 call_dissector(fr_handle, next_tvb, pinfo, tree);
1160             }
1161             else if (((octet[0] & 0xf0)== 0x40) ||
1162                      ((octet[0] & 0xf0) == 0x60))
1163             {
1164                 call_dissector(ip_handle, next_tvb, pinfo, tree);
1165             }
1166             else
1167             {
1168                 decoded = FALSE;
1169             }
1170         }
1171
1172         if (tree && !decoded) {
1173             /* Dump it as raw data. */
1174             call_dissector(data_handle, next_tvb, pinfo, tree);
1175         }
1176       }
1177       break;
1178     }
1179     break;
1180
1181   case AAL_2:
1182     switch (pinfo->pseudo_header->atm.type) {
1183       case TRAF_UMTS_FP:
1184         /* Skip first 4 bytes of message
1185         - side
1186         - length
1187         - UUI
1188         Ignoring for now... */
1189         proto_tree_add_uint(atm_tree, hf_atm_cid, tvb, 0, 0,
1190                             pinfo->pseudo_header->atm.aal2_cid);
1191         proto_item_append_text(atm_ti, " (vpi=%u vci=%u cid=%u)",
1192                                pinfo->pseudo_header->atm.vpi,
1193                                pinfo->pseudo_header->atm.vci,
1194                                pinfo->pseudo_header->atm.aal2_cid);
1195
1196         next_tvb = tvb_new_subset(tvb, 4, -1, -1);
1197         call_dissector(fp_handle, next_tvb, pinfo, tree);
1198         break;
1199
1200       default:
1201         if (tree) {
1202           /* Dump it as raw data. */
1203           call_dissector(data_handle, next_tvb, pinfo, tree);
1204           break;
1205         }
1206     }
1207     break;
1208
1209   default:
1210     if (tree) {
1211       /* Dump it as raw data. */
1212       call_dissector(data_handle, next_tvb, pinfo, tree);
1213     }
1214     break;
1215   }
1216 }
1217
1218 /*
1219  * Charles Michael Heard's HEC code, from
1220  *
1221  *      http://www.cell-relay.com/cell-relay/publications/software/CRC/32bitCRC.tutorial.html
1222  *
1223  * with the syndrome and error position tables initialized with values
1224  * computed by his "gen_syndrome_table()" and "gen_err_posn_table()" routines,
1225  * rather than by calling those routines at run time, and with various data
1226  * type cleanups and changes not to correct the header if a correctible
1227  * error was detected.
1228  */
1229 #define COSET_LEADER    0x055               /* x^6 + x^4 + x^2 + 1  */
1230
1231 static const guint8 syndrome_table[256] = {
1232         0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15,
1233         0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d,
1234         0x70, 0x77, 0x7e, 0x79, 0x6c, 0x6b, 0x62, 0x65,
1235         0x48, 0x4f, 0x46, 0x41, 0x54, 0x53, 0x5a, 0x5d,
1236         0xe0, 0xe7, 0xee, 0xe9, 0xfc, 0xfb, 0xf2, 0xf5,
1237         0xd8, 0xdf, 0xd6, 0xd1, 0xc4, 0xc3, 0xca, 0xcd,
1238         0x90, 0x97, 0x9e, 0x99, 0x8c, 0x8b, 0x82, 0x85,
1239         0xa8, 0xaf, 0xa6, 0xa1, 0xb4, 0xb3, 0xba, 0xbd,
1240         0xc7, 0xc0, 0xc9, 0xce, 0xdb, 0xdc, 0xd5, 0xd2,
1241         0xff, 0xf8, 0xf1, 0xf6, 0xe3, 0xe4, 0xed, 0xea,
1242         0xb7, 0xb0, 0xb9, 0xbe, 0xab, 0xac, 0xa5, 0xa2,
1243         0x8f, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9d, 0x9a,
1244         0x27, 0x20, 0x29, 0x2e, 0x3b, 0x3c, 0x35, 0x32,
1245         0x1f, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0d, 0x0a,
1246         0x57, 0x50, 0x59, 0x5e, 0x4b, 0x4c, 0x45, 0x42,
1247         0x6f, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7d, 0x7a,
1248         0x89, 0x8e, 0x87, 0x80, 0x95, 0x92, 0x9b, 0x9c,
1249         0xb1, 0xb6, 0xbf, 0xb8, 0xad, 0xaa, 0xa3, 0xa4,
1250         0xf9, 0xfe, 0xf7, 0xf0, 0xe5, 0xe2, 0xeb, 0xec,
1251         0xc1, 0xc6, 0xcf, 0xc8, 0xdd, 0xda, 0xd3, 0xd4,
1252         0x69, 0x6e, 0x67, 0x60, 0x75, 0x72, 0x7b, 0x7c,
1253         0x51, 0x56, 0x5f, 0x58, 0x4d, 0x4a, 0x43, 0x44,
1254         0x19, 0x1e, 0x17, 0x10, 0x05, 0x02, 0x0b, 0x0c,
1255         0x21, 0x26, 0x2f, 0x28, 0x3d, 0x3a, 0x33, 0x34,
1256         0x4e, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5c, 0x5b,
1257         0x76, 0x71, 0x78, 0x7f, 0x6a, 0x6d, 0x64, 0x63,
1258         0x3e, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2c, 0x2b,
1259         0x06, 0x01, 0x08, 0x0f, 0x1a, 0x1d, 0x14, 0x13,
1260         0xae, 0xa9, 0xa0, 0xa7, 0xb2, 0xb5, 0xbc, 0xbb,
1261         0x96, 0x91, 0x98, 0x9f, 0x8a, 0x8d, 0x84, 0x83,
1262         0xde, 0xd9, 0xd0, 0xd7, 0xc2, 0xc5, 0xcc, 0xcb,
1263         0xe6, 0xe1, 0xe8, 0xef, 0xfa, 0xfd, 0xf4, 0xf3,
1264 };
1265
1266 #define NO_ERROR_DETECTED   -128
1267 #define UNCORRECTIBLE_ERROR  128
1268
1269 static const int err_posn_table[256] = {
1270         NO_ERROR_DETECTED,      39,
1271         38,                     UNCORRECTIBLE_ERROR,
1272         37,                     UNCORRECTIBLE_ERROR,
1273         UNCORRECTIBLE_ERROR,    31,
1274         36,                     UNCORRECTIBLE_ERROR,
1275         UNCORRECTIBLE_ERROR,    8,
1276         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1277         30,                     UNCORRECTIBLE_ERROR,
1278         35,                     UNCORRECTIBLE_ERROR,
1279         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1280         UNCORRECTIBLE_ERROR,    23,
1281         7,                      UNCORRECTIBLE_ERROR,
1282         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1283         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1284         29,                     UNCORRECTIBLE_ERROR,
1285         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1286         34,                     UNCORRECTIBLE_ERROR,
1287         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1288         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1289         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1290         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1291         22,                     UNCORRECTIBLE_ERROR,
1292         6,                      UNCORRECTIBLE_ERROR,
1293         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1294         UNCORRECTIBLE_ERROR,    0,
1295         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1296         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1297         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1298         28,                     UNCORRECTIBLE_ERROR,
1299         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1300         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1301         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1302         33,                     UNCORRECTIBLE_ERROR,
1303         UNCORRECTIBLE_ERROR,    10,
1304         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1305         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1306         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1307         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1308         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1309         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1310         UNCORRECTIBLE_ERROR,    12,
1311         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1312         21,                     UNCORRECTIBLE_ERROR,
1313         UNCORRECTIBLE_ERROR,    19,
1314         5,                      UNCORRECTIBLE_ERROR,
1315         UNCORRECTIBLE_ERROR,    17,
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,    3,
1322         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1323         UNCORRECTIBLE_ERROR,    15,
1324         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1325         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1326         27,                     UNCORRECTIBLE_ERROR,
1327         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
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,    UNCORRECTIBLE_ERROR,
1334         32,                     UNCORRECTIBLE_ERROR,
1335         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1336         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1337         9,                      UNCORRECTIBLE_ERROR,
1338         UNCORRECTIBLE_ERROR,    24,
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         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1347         UNCORRECTIBLE_ERROR,    1,
1348         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1349         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1350         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1351         11,                     UNCORRECTIBLE_ERROR,
1352         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1353         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1354         20,                     UNCORRECTIBLE_ERROR,
1355         UNCORRECTIBLE_ERROR,    13,
1356         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1357         18,                     UNCORRECTIBLE_ERROR,
1358         4,                      UNCORRECTIBLE_ERROR,
1359         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1360         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1361         16,                     UNCORRECTIBLE_ERROR,
1362         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1363         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1364         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1365         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1366         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1367         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1368         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1369         UNCORRECTIBLE_ERROR,    25,
1370         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1371         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1372         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1373         2,                      UNCORRECTIBLE_ERROR,
1374         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1375         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1376         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1377         14,                     UNCORRECTIBLE_ERROR,
1378         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1379         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1380         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1381         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1382         26,                     UNCORRECTIBLE_ERROR,
1383         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1384         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1385         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1386         UNCORRECTIBLE_ERROR,    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 };
1399
1400 /*
1401  * Return an indication of whether there was an error in the cell header
1402  * and, if so, where the error was, if it was correctable.
1403  */
1404 static int
1405 get_header_err(const guint8 *cell_header)
1406 {
1407   register guint8 syndrome;
1408   register int i, err_posn;
1409
1410   syndrome = 0;
1411   for (i = 0;  i < 4;  i++)
1412     syndrome = syndrome_table[syndrome ^ cell_header[i]];
1413   syndrome ^= cell_header[4] ^ COSET_LEADER;
1414
1415   err_posn = err_posn_table [syndrome];
1416
1417   if (err_posn < 0)
1418     return NO_ERROR_DETECTED;
1419   else if (err_posn < 40)
1420     return err_posn;
1421   else
1422     return UNCORRECTIBLE_ERROR;
1423 }
1424
1425 const value_string atm_pt_vals[] = {
1426         { 0, "User data cell, congestion not experienced, SDU-type = 0" },
1427         { 1, "User data cell, congestion not experienced, SDU-type = 1" },
1428         { 2, "User data cell, congestion experienced, SDU-type = 0" },
1429         { 3, "User data cell, congestion experienced, SDU-type = 1" },
1430         { 4, "Segment OAM F5 flow related cell" },
1431         { 5, "End-to-end OAM F5 flow related cell" },
1432         { 6, "VC resource management cell" },
1433         { 0, NULL }
1434 };
1435
1436 /*
1437  * Charles Michael Heard's CRC-10 code, from
1438  *
1439  *      http://www.cell-relay.com/cell-relay/publications/software/CRC/crc10.html
1440  *
1441  * with the CRC table initialized with values computed by
1442  * his "gen_byte_crc10_table()" routine, rather than by calling that
1443  * routine at run time, and with various data type cleanups.
1444  */
1445 static const guint16 byte_crc10_table[256] = {
1446         0x0000, 0x0233, 0x0255, 0x0066, 0x0299, 0x00aa, 0x00cc, 0x02ff,
1447         0x0301, 0x0132, 0x0154, 0x0367, 0x0198, 0x03ab, 0x03cd, 0x01fe,
1448         0x0031, 0x0202, 0x0264, 0x0057, 0x02a8, 0x009b, 0x00fd, 0x02ce,
1449         0x0330, 0x0103, 0x0165, 0x0356, 0x01a9, 0x039a, 0x03fc, 0x01cf,
1450         0x0062, 0x0251, 0x0237, 0x0004, 0x02fb, 0x00c8, 0x00ae, 0x029d,
1451         0x0363, 0x0150, 0x0136, 0x0305, 0x01fa, 0x03c9, 0x03af, 0x019c,
1452         0x0053, 0x0260, 0x0206, 0x0035, 0x02ca, 0x00f9, 0x009f, 0x02ac,
1453         0x0352, 0x0161, 0x0107, 0x0334, 0x01cb, 0x03f8, 0x039e, 0x01ad,
1454         0x00c4, 0x02f7, 0x0291, 0x00a2, 0x025d, 0x006e, 0x0008, 0x023b,
1455         0x03c5, 0x01f6, 0x0190, 0x03a3, 0x015c, 0x036f, 0x0309, 0x013a,
1456         0x00f5, 0x02c6, 0x02a0, 0x0093, 0x026c, 0x005f, 0x0039, 0x020a,
1457         0x03f4, 0x01c7, 0x01a1, 0x0392, 0x016d, 0x035e, 0x0338, 0x010b,
1458         0x00a6, 0x0295, 0x02f3, 0x00c0, 0x023f, 0x000c, 0x006a, 0x0259,
1459         0x03a7, 0x0194, 0x01f2, 0x03c1, 0x013e, 0x030d, 0x036b, 0x0158,
1460         0x0097, 0x02a4, 0x02c2, 0x00f1, 0x020e, 0x003d, 0x005b, 0x0268,
1461         0x0396, 0x01a5, 0x01c3, 0x03f0, 0x010f, 0x033c, 0x035a, 0x0169,
1462         0x0188, 0x03bb, 0x03dd, 0x01ee, 0x0311, 0x0122, 0x0144, 0x0377,
1463         0x0289, 0x00ba, 0x00dc, 0x02ef, 0x0010, 0x0223, 0x0245, 0x0076,
1464         0x01b9, 0x038a, 0x03ec, 0x01df, 0x0320, 0x0113, 0x0175, 0x0346,
1465         0x02b8, 0x008b, 0x00ed, 0x02de, 0x0021, 0x0212, 0x0274, 0x0047,
1466         0x01ea, 0x03d9, 0x03bf, 0x018c, 0x0373, 0x0140, 0x0126, 0x0315,
1467         0x02eb, 0x00d8, 0x00be, 0x028d, 0x0072, 0x0241, 0x0227, 0x0014,
1468         0x01db, 0x03e8, 0x038e, 0x01bd, 0x0342, 0x0171, 0x0117, 0x0324,
1469         0x02da, 0x00e9, 0x008f, 0x02bc, 0x0043, 0x0270, 0x0216, 0x0025,
1470         0x014c, 0x037f, 0x0319, 0x012a, 0x03d5, 0x01e6, 0x0180, 0x03b3,
1471         0x024d, 0x007e, 0x0018, 0x022b, 0x00d4, 0x02e7, 0x0281, 0x00b2,
1472         0x017d, 0x034e, 0x0328, 0x011b, 0x03e4, 0x01d7, 0x01b1, 0x0382,
1473         0x027c, 0x004f, 0x0029, 0x021a, 0x00e5, 0x02d6, 0x02b0, 0x0083,
1474         0x012e, 0x031d, 0x037b, 0x0148, 0x03b7, 0x0184, 0x01e2, 0x03d1,
1475         0x022f, 0x001c, 0x007a, 0x0249, 0x00b6, 0x0285, 0x02e3, 0x00d0,
1476         0x011f, 0x032c, 0x034a, 0x0179, 0x0386, 0x01b5, 0x01d3, 0x03e0,
1477         0x021e, 0x002d, 0x004b, 0x0278, 0x0087, 0x02b4, 0x02d2, 0x00e1,
1478 };
1479
1480 /* update the data block's CRC-10 remainder one byte at a time */
1481 static guint16
1482 update_crc10_by_bytes(guint16 crc10_accum, const guint8 *data_blk_ptr,
1483     int data_blk_size)
1484 {
1485   register int i;
1486
1487   for (i = 0;  i < data_blk_size; i++) {
1488       crc10_accum = ((crc10_accum << 8) & 0x3ff)
1489                      ^ byte_crc10_table[( crc10_accum >> 2) & 0xff]
1490                                                     ^ *data_blk_ptr++;
1491   }
1492   return crc10_accum;
1493 }
1494
1495 static const value_string st_vals[] = {
1496         { 2, "BOM" },
1497         { 0, "COM" },
1498         { 1, "EOM" },
1499         { 3, "SSM" },
1500         { 0, NULL }
1501 };
1502
1503 #define OAM_TYPE_FM     1       /* Fault Management */
1504 #define OAM_TYPE_PM     2       /* Performance Management */
1505 #define OAM_TYPE_AD     8       /* Activation/Deactivation */
1506
1507 static const value_string oam_type_vals[] = {
1508         { OAM_TYPE_FM, "Fault Management" },
1509         { OAM_TYPE_PM, "Performance Management" },
1510         { OAM_TYPE_AD, "Activation/Deactivation" },
1511         { 0,           NULL }
1512 };
1513
1514 static const value_string ft_fm_vals[] = {
1515         { 0, "Alarm Indication Signal" },
1516         { 1, "Far End Receive Failure" },
1517         { 8, "OAM Cell Loopback" },
1518         { 4, "Continuity Check" },
1519         { 0, NULL }
1520 };
1521
1522 static const value_string ft_pm_vals[] = {
1523         { 0, "Forward Monitoring" },
1524         { 1, "Backward Reporting" },
1525         { 2, "Monitoring and Reporting" },
1526         { 0, NULL }
1527 };
1528
1529 static const value_string ft_ad_vals[] = {
1530         { 0, "Performance Monitoring" },
1531         { 1, "Continuity Check" },
1532         { 0, NULL }
1533 };
1534
1535
1536 /*
1537  * Check for OAM cells.
1538  * OAM F4 is VCI 3 or 4 and PT 0X0.
1539  * OAM F5 is PT 10X.
1540  */
1541 gboolean atm_is_oam_cell(const guint16 vci, const guint8 pt) 
1542 {
1543         return  (((vci == 3 || vci == 4) && ((pt & 0x5) == 0)) 
1544                 || ((pt & 0x6) == 0x4));
1545 }
1546
1547
1548 static void
1549 dissect_atm_cell(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1550                  proto_tree *atm_tree, guint aal, gboolean nni,
1551                  gboolean crc_stripped)
1552 {
1553   int          offset;
1554   proto_tree   *aal_tree;
1555   proto_item   *ti;
1556   guint8       octet;
1557   int          err;
1558   guint16      vpi;
1559   guint16      vci;
1560   guint8       pt;
1561   guint16      aal3_4_hdr, aal3_4_trlr;
1562   guint16      oam_crc;
1563   gint         length;
1564   guint16      crc10;
1565   tvbuff_t     *next_tvb;
1566   const pwatm_private_data_t * pwpd = pinfo->private_data;
1567
1568   if (NULL == pwpd) {
1569     if (!nni) {
1570           /* 
1571            * FF: ITU-T I.361 (Section 2.2) defines the cell header format 
1572            * and encoding at UNI reference point as:
1573            * 
1574            *  8 7 6 5 4 3 2 1
1575            * +-+-+-+-+-+-+-+-+
1576            * |  GFC  |  VPI  |
1577            * +-+-+-+-+-+-+-+-+
1578            * |  VPI  |  VCI  |
1579            * +-+-+-+-+-+-+-+-+
1580            * |      VCI      |
1581            * +-+-+-+-+-+-+-+-+
1582            * |  VCI  |  PT |C|
1583            * +-+-+-+-+-+-+-+-+
1584            * |   HEC (CRC)   |
1585            * +-+-+-+-+-+-+-+-+
1586            */
1587           octet = tvb_get_guint8(tvb, 0);
1588           proto_tree_add_text(atm_tree, tvb, 0, 1, "GFC: 0x%x", octet >> 4);
1589           vpi = (octet & 0xF) << 4;
1590           octet = tvb_get_guint8(tvb, 1);
1591           vpi |= octet >> 4;
1592           proto_tree_add_uint(atm_tree, hf_atm_vpi, tvb, 0, 2, vpi);
1593     } else {
1594           /* 
1595            * FF: ITU-T I.361 (Section 2.3) defines the cell header format 
1596            * and encoding at NNI reference point as:
1597            * 
1598            *  8 7 6 5 4 3 2 1
1599            * +-+-+-+-+-+-+-+-+
1600            * |      VPI      |
1601            * +-+-+-+-+-+-+-+-+
1602            * |  VPI  |  VCI  |
1603            * +-+-+-+-+-+-+-+-+
1604            * |      VCI      |
1605            * +-+-+-+-+-+-+-+-+
1606            * |  VCI  |  PT |C|
1607            * +-+-+-+-+-+-+-+-+
1608            * |   HEC (CRC)   |
1609            * +-+-+-+-+-+-+-+-+
1610            */
1611           octet = tvb_get_guint8(tvb, 0);
1612           vpi = octet << 4;
1613           octet = tvb_get_guint8(tvb, 1);
1614           vpi |= (octet & 0xF0) >> 4;
1615           proto_tree_add_uint(atm_tree, hf_atm_vpi, tvb, 0, 2, vpi);
1616     }
1617
1618     vci = (octet & 0x0F) << 12;
1619     octet = tvb_get_guint8(tvb, 2);
1620     vci |= octet << 4;
1621     octet = tvb_get_guint8(tvb, 3);
1622     vci |= octet >> 4;
1623     proto_tree_add_uint(atm_tree, hf_atm_vci, tvb, 1, 3, vci);
1624     pt = (octet >> 1) & 0x7;
1625     proto_tree_add_text(atm_tree, tvb, 3, 1, "Payload Type: %s",
1626          val_to_str(pt, atm_pt_vals, "Unknown (%u)"));
1627     proto_tree_add_text(atm_tree, tvb, 3, 1, "Cell Loss Priority: %s",
1628         (octet & 0x01) ? "Low priority" : "High priority");
1629   
1630     if (!crc_stripped) {
1631           /*
1632            * FF: parse the Header Error Check (HEC).
1633            */
1634           ti = proto_tree_add_text(atm_tree, tvb, 4, 1, 
1635                                    "Header Error Check: 0x%02x",
1636                                    tvb_get_guint8(tvb, 4));
1637           err = get_header_err(tvb_get_ptr(tvb, 0, 5));
1638           if (err == NO_ERROR_DETECTED)
1639                   proto_item_append_text(ti, " (correct)");
1640           else if (err == UNCORRECTIBLE_ERROR)
1641                   proto_item_append_text(ti, " (uncorrectable error)");
1642           else
1643                   proto_item_append_text(ti, " (error in bit %d)", err);
1644           offset = 5;
1645     } else {
1646           /*
1647            * FF: in some encapsulation modes (e.g. RFC 4717, ATM N-to-One
1648            * Cell Mode) the Header Error Check (HEC) field is stripped.
1649            * So we do nothing here.
1650            */
1651           offset = 4;
1652     }
1653   }
1654   else
1655   {
1656     offset = 0; /* For PWs. Header is decoded by PW dissector.*/
1657     pwpd = pinfo->private_data;
1658     vpi = pwpd->vpi;
1659     vci = pwpd->vci; 
1660     pt  = pwpd->pti;
1661   }
1662
1663   /*
1664    * Check for OAM cells.
1665    * XXX - do this for all AAL values, overriding whatever information
1666    * Wiretap got from the file?
1667    */
1668   if (aal == AAL_USER) {
1669     if (atm_is_oam_cell(vci,pt)) {
1670       aal = AAL_OAMCELL;
1671     }
1672   }
1673
1674   switch (aal) {
1675
1676   case AAL_1:
1677     col_set_str(pinfo->cinfo, COL_PROTOCOL, "AAL1");
1678     if (check_col(pinfo->cinfo, COL_INFO))
1679       col_clear(pinfo->cinfo, COL_INFO);
1680     ti = proto_tree_add_item(tree, proto_aal1, tvb, offset, -1, FALSE);
1681     aal_tree = proto_item_add_subtree(ti, ett_aal1);
1682     octet = tvb_get_guint8(tvb, offset);
1683     proto_tree_add_text(aal_tree, tvb, offset, 1, "CSI: %u", octet >> 7);
1684     proto_tree_add_text(aal_tree, tvb, offset, 1, "Sequence Count: %u",
1685                 (octet >> 4) & 0x7);
1686     if (check_col(pinfo->cinfo, COL_INFO)) {
1687       col_add_fstr(pinfo->cinfo, COL_INFO, "Sequence count = %u",
1688                 (octet >> 4) & 0x7);
1689     }
1690     proto_tree_add_text(aal_tree, tvb, offset, 1, "CRC: 0x%x",
1691                 (octet >> 1) & 0x7);
1692     proto_tree_add_text(aal_tree, tvb, offset, 1, "Parity: %u",
1693                 octet & 0x1);
1694     offset++;
1695
1696     proto_tree_add_text(aal_tree, tvb, offset, 47, "Payload");
1697     break;
1698
1699   case AAL_3_4:
1700     /*
1701      * XXX - or should this be the CS PDU?
1702      */
1703     col_set_str(pinfo->cinfo, COL_PROTOCOL, "AAL3/4");
1704     if (check_col(pinfo->cinfo, COL_INFO))
1705       col_clear(pinfo->cinfo, COL_INFO);
1706     ti = proto_tree_add_item(tree, proto_aal3_4, tvb, offset, -1, FALSE);
1707     aal_tree = proto_item_add_subtree(ti, ett_aal3_4);
1708     aal3_4_hdr = tvb_get_ntohs(tvb, offset);
1709     if (check_col(pinfo->cinfo, COL_INFO)) {
1710       col_add_fstr(pinfo->cinfo, COL_INFO, "%s, sequence number = %u",
1711                 val_to_str(aal3_4_hdr >> 14, st_vals, "Unknown (%u)"),
1712                 (aal3_4_hdr >> 10) & 0xF);
1713     }
1714     proto_tree_add_text(aal_tree, tvb, offset, 2, "Segment Type: %s",
1715                 val_to_str(aal3_4_hdr >> 14, st_vals, "Unknown (%u)"));
1716     proto_tree_add_text(aal_tree, tvb, offset, 2, "Sequence Number: %u",
1717                 (aal3_4_hdr >> 10) & 0xF);
1718     proto_tree_add_text(aal_tree, tvb, offset, 2, "Multiplex ID: %u",
1719                 aal3_4_hdr & 0x3FF);
1720     offset += 2;
1721
1722     proto_tree_add_text(aal_tree, tvb, offset, 44, "Information");
1723     offset += 44;
1724
1725     aal3_4_trlr = tvb_get_ntohs(tvb, offset);
1726     proto_tree_add_text(aal_tree, tvb, offset, 2, "Length Indicator: %u",
1727                 (aal3_4_trlr >> 10) & 0x3F);
1728     length = tvb_length_remaining(tvb, 5);
1729     crc10 = update_crc10_by_bytes(0, tvb_get_ptr(tvb, 5, length),
1730         length);
1731     proto_tree_add_text(aal_tree, tvb, offset, 2, "CRC: 0x%03x (%s)",
1732                 aal3_4_trlr & 0x3FF,
1733                 (crc10 == 0) ? "correct" : "incorrect");
1734     break;
1735
1736   case AAL_OAMCELL:
1737     if (NULL == pwpd || pwpd->enable_fill_columns_by_atm_dissector)
1738     {
1739       col_set_str(pinfo->cinfo, COL_PROTOCOL, "OAM AAL");
1740       if (check_col(pinfo->cinfo, COL_INFO))
1741         col_clear(pinfo->cinfo, COL_INFO);
1742     }
1743     ti = proto_tree_add_item(tree, proto_oamaal, tvb, offset, -1, FALSE);
1744     aal_tree = proto_item_add_subtree(ti, ett_oamaal);
1745     octet = tvb_get_guint8(tvb, offset);
1746     if (NULL == pwpd || pwpd->enable_fill_columns_by_atm_dissector)
1747     {
1748       if (check_col(pinfo->cinfo, COL_INFO))
1749         col_add_fstr(pinfo->cinfo, COL_INFO, "%s",
1750                 val_to_str(octet >> 4, oam_type_vals, "Unknown (%u)"));
1751     }
1752     proto_tree_add_text(aal_tree, tvb, offset, 1, "OAM Type: %s",
1753                 val_to_str(octet >> 4, oam_type_vals, "Unknown (%u)"));
1754     switch (octet >> 4) {
1755
1756     case OAM_TYPE_FM:
1757       proto_tree_add_text(aal_tree, tvb, offset, 1, "Function Type: %s",
1758                 val_to_str(octet & 0x0F, ft_fm_vals, "Unknown (%u)"));
1759       break;
1760
1761     case OAM_TYPE_PM:
1762       proto_tree_add_text(aal_tree, tvb, offset, 1, "Function Type: %s",
1763                 val_to_str(octet & 0x0F, ft_pm_vals, "Unknown (%u)"));
1764       break;
1765
1766     case OAM_TYPE_AD:
1767       proto_tree_add_text(aal_tree, tvb, offset, 1, "Function Type: %s",
1768                 val_to_str(octet & 0x0F, ft_ad_vals, "Unknown (%u)"));
1769       break;
1770
1771     default:
1772       proto_tree_add_text(aal_tree, tvb, offset, 1, "Function Type: %u",
1773                 octet & 0x0F);
1774       break;
1775     }
1776     offset += 1;
1777
1778     proto_tree_add_text(aal_tree, tvb, offset, 45, "Function-specific information");
1779     offset += 45;
1780
1781     length = tvb_length_remaining(tvb, 5);
1782     crc10 = update_crc10_by_bytes(0, tvb_get_ptr(tvb, 5, length),
1783         length);
1784     oam_crc = tvb_get_ntohs(tvb, offset);
1785     proto_tree_add_text(aal_tree, tvb, offset, 2, "CRC-10: 0x%03x (%s)",
1786                 oam_crc & 0x3FF,
1787                 (crc10 == 0) ? "correct" : "incorrect");
1788     break;
1789
1790   default:
1791     next_tvb = tvb_new_subset(tvb, offset, -1, -1);
1792     call_dissector(data_handle, next_tvb, pinfo, tree);
1793     break;
1794   }
1795 }
1796
1797 static void
1798 dissect_atm_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1799     gboolean truncated)
1800 {
1801   proto_tree   *atm_tree = NULL;
1802   proto_item   *atm_ti = NULL;
1803   gboolean     pseudowire_mode = (NULL != pinfo->private_data);
1804   
1805   if ( pinfo->pseudo_header->atm.aal == AAL_5 &&
1806         pinfo->pseudo_header->atm.type == TRAF_LANE &&
1807         dissect_lanesscop ) {
1808         pinfo->pseudo_header->atm.aal = AAL_SIGNALLING;
1809   }
1810
1811   col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATM");
1812
1813   if (!pseudowire_mode) {
1814     switch (pinfo->pseudo_header->atm.channel) {
1815
1816     case 0:
1817       /* Traffic from DTE to DCE. */
1818       if (check_col(pinfo->cinfo, COL_RES_DL_DST))
1819         col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DCE");
1820       if (check_col(pinfo->cinfo, COL_RES_DL_SRC))
1821         col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DTE");
1822       break;
1823
1824     case 1:
1825       /* Traffic from DCE to DTE. */
1826       if (check_col(pinfo->cinfo, COL_RES_DL_DST))
1827         col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DTE");
1828       if (check_col(pinfo->cinfo, COL_RES_DL_SRC))
1829         col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DCE");
1830       break;
1831     }
1832   }
1833
1834   if (check_col(pinfo->cinfo, COL_INFO)) {
1835     if (pinfo->pseudo_header->atm.aal == AAL_5) {
1836       col_add_fstr(pinfo->cinfo, COL_INFO, "AAL5 %s",
1837                 val_to_str(pinfo->pseudo_header->atm.type, aal5_hltype_vals,
1838                                 "Unknown traffic type (%u)"));
1839     } else {
1840       col_add_str(pinfo->cinfo, COL_INFO,
1841                 val_to_str(pinfo->pseudo_header->atm.aal, aal_vals,
1842                         "Unknown AAL (%u)"));
1843     }
1844   }
1845
1846   if (tree) {
1847     atm_ti = proto_tree_add_protocol_format(tree, proto_atm, tvb, 0, 0, "ATM");
1848     atm_tree = proto_item_add_subtree(atm_ti, ett_atm);
1849
1850     if (!pseudowire_mode) {
1851       switch (pinfo->pseudo_header->atm.channel) {
1852
1853       case 0:
1854         /* Traffic from DTE to DCE. */
1855         proto_tree_add_text(atm_tree, tvb, 0, 0, "Channel: DTE->DCE");
1856         break;
1857
1858       case 1:
1859         /* Traffic from DCE to DTE. */
1860         proto_tree_add_text(atm_tree, tvb, 0, 0, "Channel: DCE->DTE");
1861         break;
1862
1863       default:
1864         /* Sniffers shouldn't provide anything other than 0 or 1. */
1865         proto_tree_add_text(atm_tree, tvb, 0, 0, "Channel: %u",
1866                 pinfo->pseudo_header->atm.channel);
1867         break;
1868       }
1869     }
1870
1871     proto_tree_add_uint_format_value(atm_tree, hf_atm_aal, tvb, 0, 0,
1872         pinfo->pseudo_header->atm.aal,
1873         "%s",
1874         val_to_str(pinfo->pseudo_header->atm.aal, aal_vals,
1875           "Unknown AAL (%u)"));
1876   }
1877   if (pinfo->pseudo_header->atm.flags & ATM_RAW_CELL) {
1878     /* This is a single cell, with the cell header at the beginning. */
1879     proto_item_set_len(atm_ti, 5);
1880     dissect_atm_cell(tvb, pinfo, tree, atm_tree, 
1881                      pinfo->pseudo_header->atm.aal, FALSE, FALSE);
1882   } else {
1883     /* This is a reassembled PDU. */
1884     dissect_reassembled_pdu(tvb, pinfo, tree, atm_tree, atm_ti, truncated);
1885   }
1886 }
1887
1888 static void
1889 dissect_atm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1890 {
1891   dissect_atm_common(tvb, pinfo, tree, TRUE);
1892 }
1893
1894 static void
1895 dissect_atm_untruncated(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1896 {
1897   dissect_atm_common(tvb, pinfo, tree, FALSE);
1898 }
1899
1900 static void
1901 dissect_atm_oam_cell(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1902 {
1903   proto_tree   *atm_tree = NULL;
1904   proto_item   *atm_ti = NULL;
1905   gboolean     pseudowire_mode = (NULL != pinfo->private_data);
1906   
1907   col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATM");
1908
1909   if (!pseudowire_mode) {
1910     if (tree) {
1911       atm_ti = proto_tree_add_protocol_format(tree, proto_atm, tvb, 0, 0, "ATM");
1912       atm_tree = proto_item_add_subtree(atm_ti, ett_atm);
1913     }
1914   }
1915
1916   dissect_atm_cell(tvb, pinfo, tree, atm_tree, AAL_OAMCELL, FALSE, FALSE);
1917 }
1918
1919
1920 void
1921 proto_register_atm(void)
1922 {
1923         static hf_register_info hf[] = {
1924                 { &hf_atm_aal,
1925                 { "AAL",                "atm.aal", FT_UINT8, BASE_DEC, VALS(aal_vals), 0x0,
1926                         NULL, HFILL }},
1927
1928                 { &hf_atm_vpi,
1929                 { "VPI",                "atm.vpi", FT_UINT8, BASE_DEC, NULL, 0x0,
1930                         NULL, HFILL }},
1931
1932                 { &hf_atm_vci,
1933                 { "VCI",                "atm.vci", FT_UINT16, BASE_DEC, NULL, 0x0,
1934                         NULL, HFILL }},
1935
1936                 { &hf_atm_cid,
1937                 { "CID",                "atm.cid", FT_UINT8, BASE_DEC, NULL, 0x0,
1938                         NULL, HFILL }},
1939
1940         };
1941         static gint *ett[] = {
1942                 &ett_atm,
1943                 &ett_ilmi,
1944                 &ett_aal1,
1945                 &ett_aal3_4,
1946                 &ett_oamaal,
1947                 &ett_atm_lane,
1948                 &ett_atm_lane_lc_lan_dest,
1949                 &ett_atm_lane_lc_lan_dest_rd,
1950                 &ett_atm_lane_lc_flags,
1951                 &ett_atm_lane_lc_tlv,
1952         };
1953         
1954         module_t *atm_module;
1955         
1956         proto_atm = proto_register_protocol("ATM", "ATM", "atm");
1957         proto_aal1 = proto_register_protocol("ATM AAL1", "AAL1", "aal1");
1958         proto_aal3_4 = proto_register_protocol("ATM AAL3/4", "AAL3/4", "aal3_4");
1959         proto_oamaal = proto_register_protocol("ATM OAM AAL", "OAM AAL", "oamaal");
1960         proto_register_field_array(proto_atm, hf, array_length(hf));
1961         proto_register_subtree_array(ett, array_length(ett));
1962
1963         proto_ilmi = proto_register_protocol("ILMI", "ILMI", "ilmi");
1964
1965         register_dissector("ilmi", dissect_ilmi, proto_ilmi);
1966
1967         proto_atm_lane = proto_register_protocol("ATM LAN Emulation",
1968             "ATM LANE", "lane");
1969
1970         register_dissector("lane", dissect_lane, proto_atm_lane);
1971         register_dissector("atm_untruncated", dissect_atm_untruncated, proto_atm);
1972         register_dissector("atm_truncated", dissect_atm, proto_atm);
1973         register_dissector("atm_oam_cell", dissect_atm_oam_cell, proto_oamaal);
1974         
1975         atm_module = prefs_register_protocol ( proto_atm, NULL );
1976         prefs_register_bool_preference ( atm_module, "dissect_lane_as_sscop", "Dissect LANE as SSCOP",
1977                 "Autodection between LANE and SSCOP is hard. As default LANE is preferred",
1978                 &dissect_lanesscop);
1979 }
1980
1981 void
1982 proto_reg_handoff_atm(void)
1983 {
1984         dissector_handle_t atm_handle, atm_untruncated_handle;
1985
1986         /*
1987          * Get handles for the Ethernet, Token Ring, Frame Relay, LLC,
1988          * SSCOP, LANE, and ILMI dissectors.
1989          */
1990         eth_withoutfcs_handle = find_dissector("eth_withoutfcs");
1991         tr_handle = find_dissector("tr");
1992         fr_handle = find_dissector("fr");
1993         llc_handle = find_dissector("llc");
1994         sscop_handle = find_dissector("sscop");
1995         lane_handle = find_dissector("lane");
1996         ilmi_handle = find_dissector("ilmi");
1997         ppp_handle = find_dissector("ppp");
1998         eth_handle = find_dissector("eth");
1999         ip_handle = find_dissector("ip");
2000         data_handle = find_dissector("data");
2001         fp_handle = find_dissector("fp");
2002
2003         atm_handle = create_dissector_handle(dissect_atm, proto_atm);
2004         dissector_add("wtap_encap", WTAP_ENCAP_ATM_PDUS, atm_handle);
2005
2006         atm_untruncated_handle = create_dissector_handle(dissect_atm_untruncated,
2007             proto_atm);
2008         dissector_add("wtap_encap", WTAP_ENCAP_ATM_PDUS_UNTRUNCATED,
2009             atm_untruncated_handle);
2010 }