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