add details for doxygen
[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.65 2003/09/06 01:21:00 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, proto_ilmi, ett_ilmi, FALSE);
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 traffic type for AAL5 traffic, and the VPI and VCI,
929    * from the pseudo-header.
930    */
931   if (pinfo->pseudo_header->atm.aal == AAL_5) {
932     proto_tree_add_text(atm_tree, tvb, 0, 0, "Traffic type: %s",
933                 val_to_str(pinfo->pseudo_header->atm.type, aal5_hltype_vals,
934                 "Unknown AAL5 traffic type (%u)"));
935     switch (pinfo->pseudo_header->atm.type) {
936
937     case TRAF_VCMX:
938       proto_tree_add_text(atm_tree, tvb, 0, 0, "VC multiplexed traffic type: %s",
939                 val_to_str(pinfo->pseudo_header->atm.subtype,
940                         vcmx_type_vals, "Unknown VCMX traffic type (%u)"));
941       break;
942
943     case TRAF_LANE:
944       proto_tree_add_text(atm_tree, tvb, 0, 0, "LANE traffic type: %s",
945                 val_to_str(pinfo->pseudo_header->atm.subtype,
946                         lane_type_vals, "Unknown LANE traffic type (%u)"));
947       break;
948
949     case TRAF_IPSILON:
950       proto_tree_add_text(atm_tree, tvb, 0, 0, "Ipsilon traffic type: %s",
951                 val_to_str(pinfo->pseudo_header->atm.subtype,
952                         ipsilon_type_vals, "Unknown Ipsilon traffic type (%u)"));
953       break;
954     }
955   }
956   proto_tree_add_uint(atm_tree, hf_atm_vpi, tvb, 0, 0,
957                 pinfo->pseudo_header->atm.vpi);
958   proto_tree_add_uint(atm_tree, hf_atm_vci, tvb, 0, 0,
959                 pinfo->pseudo_header->atm.vci);
960
961   next_tvb = tvb;
962   if (truncated) {
963     /*
964      * The packet data does not include stuff such as the AAL5
965      * trailer.
966      */
967     if (pinfo->pseudo_header->atm.cells != 0) {
968       /*
969        * If the cell count is 0, assume it means we don't know how
970        * many cells it was.
971        *
972        * XXX - also assume it means we don't know what was in the AAL5
973        * trailer.  We may, however, find some capture program that can
974        * give us the AAL5 trailer information but not the cell count,
975        * in which case we need some other way of indicating whether we
976        * have the AAL5 trailer information.
977        */
978       if (tree) {
979         proto_tree_add_text(atm_tree, tvb, 0, 0, "Cells: %u",
980                 pinfo->pseudo_header->atm.cells);
981         proto_tree_add_text(atm_tree, tvb, 0, 0, "AAL5 UU: 0x%02x",
982                 pinfo->pseudo_header->atm.aal5t_u2u >> 8);
983         proto_tree_add_text(atm_tree, tvb, 0, 0, "AAL5 CPI: 0x%02x",
984                 pinfo->pseudo_header->atm.aal5t_u2u & 0xFF);
985         proto_tree_add_text(atm_tree, tvb, 0, 0, "AAL5 len: %u",
986                 pinfo->pseudo_header->atm.aal5t_len);
987         proto_tree_add_text(atm_tree, tvb, 0, 0, "AAL5 CRC: 0x%08X",
988                 pinfo->pseudo_header->atm.aal5t_chksum);
989       }
990     }
991   } else {
992     /*
993      * The packet data includes stuff such as the AAL5 trailer, if
994      * it wasn't cut off by the snapshot length.
995      * Decode the trailer, if present, and then chop it off.
996      */
997     length = tvb_length(tvb);
998     reported_length = tvb_reported_length(tvb);
999     if ((reported_length % 48) == 0) {
1000       /*
1001        * Reported length is a multiple of 48, so we can presumably
1002        * divide it by 48 to get the number of cells.
1003        */
1004       proto_tree_add_text(atm_tree, tvb, 0, 0, "Cells: %u",
1005                 reported_length/48);
1006     }
1007     if (length >= reported_length) {
1008       /*
1009        * XXX - what if the packet is truncated?  Can that happen?
1010        * What if you capture with Windows Sniffer on an ATM link
1011        * and tell it not to save the entire packet?  What happens
1012        * to the trailer?
1013        */
1014       aal5_length = tvb_get_ntohs(tvb, length - 6);
1015
1016       /*
1017        * Check for sanity in the AAL5 length.  It must be > 0
1018        * and must be less than the amount of space left after
1019        * we remove the trailer.
1020        *
1021        * If it's not sane, assume we don't have a trailer.
1022        */
1023       if (aal5_length > 0 && aal5_length <= length - 8) {
1024         /*
1025          * How much padding is there?
1026          */
1027         pad_length = length - aal5_length - 8;
1028
1029         /*
1030          * There is no reason for more than 47 bytes of padding.
1031          * The most padding you can have would be 7 bytes at the
1032          * end of the next-to-last cell (8 bytes after the end of
1033          * the data means you can fit the trailer in that cell),
1034          * plus 40 bytes in the last cell (with the last 8 bytes
1035          * being padding).
1036          *
1037          * If there's more than 47 bytes of padding, assume we don't
1038          * have a trailer.
1039          */
1040         if (pad_length <= 47) {
1041           if (tree) {
1042             if (pad_length > 0) {
1043               proto_tree_add_text(atm_tree, tvb, aal5_length, pad_length,
1044                 "Padding");
1045             }
1046             proto_tree_add_text(atm_tree, tvb, length - 8, 1, "AAL5 UU: 0x%02x",
1047                 tvb_get_guint8(tvb, length - 8));
1048             proto_tree_add_text(atm_tree, tvb, length - 7, 1, "AAL5 CPI: 0x%02x",
1049                 tvb_get_guint8(tvb, length - 7));
1050             proto_tree_add_text(atm_tree, tvb, length - 6, 2, "AAL5 len: %u",
1051                 aal5_length);
1052             crc = tvb_get_ntohl(tvb, length - 4);
1053             calc_crc = update_crc(0xFFFFFFFF, tvb_get_ptr(tvb, 0, length),
1054                 length);
1055             proto_tree_add_text(atm_tree, tvb, length - 4, 4,
1056                 "AAL5 CRC: 0x%08X (%s)", crc,
1057                 (calc_crc == 0xC704DD7B) ? "correct" : "incorrect");
1058           }
1059           next_tvb = tvb_new_subset(tvb, 0, aal5_length, aal5_length);
1060         }
1061       }
1062     }
1063   }
1064
1065   switch (pinfo->pseudo_header->atm.aal) {
1066
1067   case AAL_SIGNALLING:
1068     call_dissector(sscop_handle, next_tvb, pinfo, tree);
1069     break;
1070
1071   case AAL_5:
1072     switch (pinfo->pseudo_header->atm.type) {
1073
1074     case TRAF_LLCMX:
1075       call_dissector(llc_handle, next_tvb, pinfo, tree);
1076       break;
1077
1078     case TRAF_LANE:
1079       call_dissector(lane_handle, next_tvb, pinfo, tree);
1080       break;
1081
1082     case TRAF_ILMI:
1083       call_dissector(ilmi_handle, next_tvb, pinfo, tree);
1084       break;
1085
1086     default:
1087       if (tree) {
1088         /* Dump it as raw data. */
1089         call_dissector(data_handle, next_tvb, pinfo, tree);
1090         break;
1091       }
1092     }
1093     break;
1094
1095   default:
1096     if (tree) {
1097       /* Dump it as raw data. */
1098       call_dissector(data_handle, next_tvb, pinfo, tree);
1099     }
1100     break;
1101   }
1102 }
1103
1104 /*
1105  * Charles Michael Heard's HEC code, from
1106  *
1107  *      http://cell-relay.indiana.edu/cell-relay/publications/software/CRC/32bitCRC.tutorial.html
1108  *
1109  * with the syndrome and error position tables initialized with values
1110  * computed by his "gen_syndrome_table()" and "gen_err_posn_table()" routines,
1111  * rather than by calling those routines at run time, and with various data
1112  * type cleanups and changes not to correct the header if a correctible
1113  * error was detected.
1114  */
1115 #define COSET_LEADER    0x055               /* x^6 + x^4 + x^2 + 1  */
1116
1117 static const guint8 syndrome_table[256] = {
1118         0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15,
1119         0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d,
1120         0x70, 0x77, 0x7e, 0x79, 0x6c, 0x6b, 0x62, 0x65,
1121         0x48, 0x4f, 0x46, 0x41, 0x54, 0x53, 0x5a, 0x5d,
1122         0xe0, 0xe7, 0xee, 0xe9, 0xfc, 0xfb, 0xf2, 0xf5,
1123         0xd8, 0xdf, 0xd6, 0xd1, 0xc4, 0xc3, 0xca, 0xcd,
1124         0x90, 0x97, 0x9e, 0x99, 0x8c, 0x8b, 0x82, 0x85,
1125         0xa8, 0xaf, 0xa6, 0xa1, 0xb4, 0xb3, 0xba, 0xbd,
1126         0xc7, 0xc0, 0xc9, 0xce, 0xdb, 0xdc, 0xd5, 0xd2,
1127         0xff, 0xf8, 0xf1, 0xf6, 0xe3, 0xe4, 0xed, 0xea,
1128         0xb7, 0xb0, 0xb9, 0xbe, 0xab, 0xac, 0xa5, 0xa2,
1129         0x8f, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9d, 0x9a,
1130         0x27, 0x20, 0x29, 0x2e, 0x3b, 0x3c, 0x35, 0x32,
1131         0x1f, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0d, 0x0a,
1132         0x57, 0x50, 0x59, 0x5e, 0x4b, 0x4c, 0x45, 0x42,
1133         0x6f, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7d, 0x7a,
1134         0x89, 0x8e, 0x87, 0x80, 0x95, 0x92, 0x9b, 0x9c,
1135         0xb1, 0xb6, 0xbf, 0xb8, 0xad, 0xaa, 0xa3, 0xa4,
1136         0xf9, 0xfe, 0xf7, 0xf0, 0xe5, 0xe2, 0xeb, 0xec,
1137         0xc1, 0xc6, 0xcf, 0xc8, 0xdd, 0xda, 0xd3, 0xd4,
1138         0x69, 0x6e, 0x67, 0x60, 0x75, 0x72, 0x7b, 0x7c,
1139         0x51, 0x56, 0x5f, 0x58, 0x4d, 0x4a, 0x43, 0x44,
1140         0x19, 0x1e, 0x17, 0x10, 0x05, 0x02, 0x0b, 0x0c,
1141         0x21, 0x26, 0x2f, 0x28, 0x3d, 0x3a, 0x33, 0x34,
1142         0x4e, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5c, 0x5b,
1143         0x76, 0x71, 0x78, 0x7f, 0x6a, 0x6d, 0x64, 0x63,
1144         0x3e, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2c, 0x2b,
1145         0x06, 0x01, 0x08, 0x0f, 0x1a, 0x1d, 0x14, 0x13,
1146         0xae, 0xa9, 0xa0, 0xa7, 0xb2, 0xb5, 0xbc, 0xbb,
1147         0x96, 0x91, 0x98, 0x9f, 0x8a, 0x8d, 0x84, 0x83,
1148         0xde, 0xd9, 0xd0, 0xd7, 0xc2, 0xc5, 0xcc, 0xcb,
1149         0xe6, 0xe1, 0xe8, 0xef, 0xfa, 0xfd, 0xf4, 0xf3,
1150 };
1151
1152 #define NO_ERROR_DETECTED   -128
1153 #define UNCORRECTIBLE_ERROR  128
1154
1155 static const int err_posn_table[256] = {
1156         NO_ERROR_DETECTED,      37,
1157         36,                     UNCORRECTIBLE_ERROR,
1158         35,                     UNCORRECTIBLE_ERROR,
1159         UNCORRECTIBLE_ERROR,    29,
1160         34,                     UNCORRECTIBLE_ERROR,
1161         UNCORRECTIBLE_ERROR,    6,
1162         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1163         28,                     UNCORRECTIBLE_ERROR,
1164         33,                     UNCORRECTIBLE_ERROR,
1165         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1166         UNCORRECTIBLE_ERROR,    21,
1167         5,                      UNCORRECTIBLE_ERROR,
1168         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1169         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1170         27,                     UNCORRECTIBLE_ERROR,
1171         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1172         32,                     UNCORRECTIBLE_ERROR,
1173         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1174         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1175         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1176         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1177         20,                     UNCORRECTIBLE_ERROR,
1178         4,                      UNCORRECTIBLE_ERROR,
1179         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1180         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1181         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1182         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1183         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1184         26,                     UNCORRECTIBLE_ERROR,
1185         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1186         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1187         UNCORRECTIBLE_ERROR,    UNCORRECTIBLE_ERROR,
1188 };
1189
1190 /*
1191  * Return an indication of whether there was an error in the cell header
1192  * and, if so, where the error was, if it was correctable.
1193  */
1194 static int
1195 get_header_err(const guint8 *cell_header)
1196 {
1197   register guint8 syndrome;
1198   register int i, err_posn;
1199
1200   syndrome = 0;
1201   for (i = 0;  i < 4;  i++)
1202     syndrome = syndrome_table[syndrome ^ cell_header[i]];
1203   syndrome ^= cell_header[4] ^ COSET_LEADER;
1204
1205   err_posn = err_posn_table [syndrome];
1206
1207   if (err_posn < 0)
1208     return NO_ERROR_DETECTED;
1209   else if (err_posn < 40)
1210     return err_posn;
1211   else
1212     return UNCORRECTIBLE_ERROR;
1213 }
1214
1215 static const value_string pt_vals[] = {
1216         { 0, "User data cell, congestion not experienced, SDU-type = 0" },
1217         { 1, "User data cell, congestion not experienced, SDU-type = 1" },
1218         { 2, "User data cell, congestion experienced, SDU-type = 0" },
1219         { 3, "User data cell, congestion experienced, SDU-type = 1" },
1220         { 4, "Segment OAM F5 flow related cell" },
1221         { 5, "End-to-end OAM F5 flow related cell" },
1222         { 0, NULL }
1223 };
1224
1225 /*
1226  * Charles Michael Heard's CRC-10 code, from
1227  *
1228  *      http://cell-relay.indiana.edu/cell-relay/publications/software/CRC/crc10.html
1229  *
1230  * with the CRC table initialized with values computed by
1231  * his "gen_byte_crc10_table()" routine, rather than by calling that
1232  * routine at run time, and with various data type cleanups.
1233  */
1234 static const guint16 byte_crc10_table[256] = {
1235         0x0000, 0x0233, 0x0255, 0x0066, 0x0299, 0x00aa, 0x00cc, 0x02ff,
1236         0x0301, 0x0132, 0x0154, 0x0367, 0x0198, 0x03ab, 0x03cd, 0x01fe,
1237         0x0031, 0x0202, 0x0264, 0x0057, 0x02a8, 0x009b, 0x00fd, 0x02ce,
1238         0x0330, 0x0103, 0x0165, 0x0356, 0x01a9, 0x039a, 0x03fc, 0x01cf,
1239         0x0062, 0x0251, 0x0237, 0x0004, 0x02fb, 0x00c8, 0x00ae, 0x029d,
1240         0x0363, 0x0150, 0x0136, 0x0305, 0x01fa, 0x03c9, 0x03af, 0x019c,
1241         0x0053, 0x0260, 0x0206, 0x0035, 0x02ca, 0x00f9, 0x009f, 0x02ac,
1242         0x0352, 0x0161, 0x0107, 0x0334, 0x01cb, 0x03f8, 0x039e, 0x01ad,
1243         0x00c4, 0x02f7, 0x0291, 0x00a2, 0x025d, 0x006e, 0x0008, 0x023b,
1244         0x03c5, 0x01f6, 0x0190, 0x03a3, 0x015c, 0x036f, 0x0309, 0x013a,
1245         0x00f5, 0x02c6, 0x02a0, 0x0093, 0x026c, 0x005f, 0x0039, 0x020a,
1246         0x03f4, 0x01c7, 0x01a1, 0x0392, 0x016d, 0x035e, 0x0338, 0x010b,
1247         0x00a6, 0x0295, 0x02f3, 0x00c0, 0x023f, 0x000c, 0x006a, 0x0259,
1248         0x03a7, 0x0194, 0x01f2, 0x03c1, 0x013e, 0x030d, 0x036b, 0x0158,
1249         0x0097, 0x02a4, 0x02c2, 0x00f1, 0x020e, 0x003d, 0x005b, 0x0268,
1250         0x0396, 0x01a5, 0x01c3, 0x03f0, 0x010f, 0x033c, 0x035a, 0x0169,
1251         0x0188, 0x03bb, 0x03dd, 0x01ee, 0x0311, 0x0122, 0x0144, 0x0377,
1252         0x0289, 0x00ba, 0x00dc, 0x02ef, 0x0010, 0x0223, 0x0245, 0x0076,
1253         0x01b9, 0x038a, 0x03ec, 0x01df, 0x0320, 0x0113, 0x0175, 0x0346,
1254         0x02b8, 0x008b, 0x00ed, 0x02de, 0x0021, 0x0212, 0x0274, 0x0047,
1255         0x01ea, 0x03d9, 0x03bf, 0x018c, 0x0373, 0x0140, 0x0126, 0x0315,
1256         0x02eb, 0x00d8, 0x00be, 0x028d, 0x0072, 0x0241, 0x0227, 0x0014,
1257         0x01db, 0x03e8, 0x038e, 0x01bd, 0x0342, 0x0171, 0x0117, 0x0324,
1258         0x02da, 0x00e9, 0x008f, 0x02bc, 0x0043, 0x0270, 0x0216, 0x0025,
1259         0x014c, 0x037f, 0x0319, 0x012a, 0x03d5, 0x01e6, 0x0180, 0x03b3,
1260         0x024d, 0x007e, 0x0018, 0x022b, 0x00d4, 0x02e7, 0x0281, 0x00b2,
1261         0x017d, 0x034e, 0x0328, 0x011b, 0x03e4, 0x01d7, 0x01b1, 0x0382,
1262         0x027c, 0x004f, 0x0029, 0x021a, 0x00e5, 0x02d6, 0x02b0, 0x0083,
1263         0x012e, 0x031d, 0x037b, 0x0148, 0x03b7, 0x0184, 0x01e2, 0x03d1,
1264         0x022f, 0x001c, 0x007a, 0x0249, 0x00b6, 0x0285, 0x02e3, 0x00d0,
1265         0x011f, 0x032c, 0x034a, 0x0179, 0x0386, 0x01b5, 0x01d3, 0x03e0,
1266         0x021e, 0x002d, 0x004b, 0x0278, 0x0087, 0x02b4, 0x02d2, 0x00e1,
1267 };
1268
1269 /* update the data block's CRC-10 remainder one byte at a time */
1270 static guint16
1271 update_crc10_by_bytes(guint16 crc10_accum, const guint8 *data_blk_ptr,
1272     int data_blk_size)
1273 {
1274   register int i;
1275
1276   for (i = 0;  i < data_blk_size; i++) {
1277       crc10_accum = ((crc10_accum << 8) & 0x3ff)
1278                      ^ byte_crc10_table[( crc10_accum >> 2) & 0xff]
1279                                                     ^ *data_blk_ptr++;
1280   }
1281   return crc10_accum;
1282 }
1283
1284 static const value_string st_vals[] = {
1285         { 2, "BOM" },
1286         { 0, "COM" },
1287         { 1, "EOM" },
1288         { 3, "SSM" },
1289         { 0, NULL }
1290 };
1291
1292 #define OAM_TYPE_FM     1       /* Fault Management */
1293 #define OAM_TYPE_PM     2       /* Performance Management */
1294 #define OAM_TYPE_AD     8       /* Activation/Deactivation */
1295
1296 static const value_string oam_type_vals[] = {
1297         { OAM_TYPE_FM, "Fault Management" },
1298         { OAM_TYPE_PM, "Performance Management" },
1299         { OAM_TYPE_AD, "Activation/Deactivation" },
1300         { 0,           NULL }
1301 };
1302
1303 static const value_string ft_fm_vals[] = {
1304         { 0, "Alarm Indication Signal" },
1305         { 1, "Far End Receive Failure" },
1306         { 8, "OAM Cell Loopback" },
1307         { 4, "Continuity Check" },
1308         { 0, NULL }
1309 };
1310
1311 static const value_string ft_pm_vals[] = {
1312         { 0, "Forward Monitoring" },
1313         { 1, "Backward Reporting" },
1314         { 2, "Monitoring and Reporting" },
1315         { 0, NULL }
1316 };
1317
1318 static const value_string ft_ad_vals[] = {
1319         { 0, "Performance Monitoring" },
1320         { 1, "Continuity Check" },
1321         { 0, NULL }
1322 };
1323
1324 static void
1325 dissect_atm_cell(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1326     proto_tree *atm_tree)
1327 {
1328   int          offset;
1329   proto_tree   *aal_tree;
1330   proto_item   *ti;
1331   guint8       octet;
1332   int          err;
1333   guint8       vpi;
1334   guint16      vci;
1335   guint16      aal3_4_hdr, aal3_4_trlr;
1336   guint16      oam_crc;
1337   gint         length;
1338   guint16      crc10;
1339   tvbuff_t     *next_tvb;
1340
1341   octet = tvb_get_guint8(tvb, 0);
1342   proto_tree_add_text(atm_tree, tvb, 0, 1, "GFC: 0x%x", octet >> 4);
1343   vpi = (octet & 0xF0) << 4;
1344   octet = tvb_get_guint8(tvb, 1);
1345   vpi |= octet >> 4;
1346   proto_tree_add_uint(atm_tree, hf_atm_vpi, tvb, 0, 2, vpi);
1347   vci = (octet & 0x0F) << 12;
1348   octet = tvb_get_guint8(tvb, 2);
1349   vci |= octet << 4;
1350   octet = tvb_get_guint8(tvb, 3);
1351   vci |= octet >> 4;
1352   proto_tree_add_uint(atm_tree, hf_atm_vci, tvb, 1, 3, vci);
1353   proto_tree_add_text(atm_tree, tvb, 3, 1, "Payload Type: %s",
1354         val_to_str((octet >> 1) & 0x7, pt_vals, "Unknown (%u)"));
1355   proto_tree_add_text(atm_tree, tvb, 3, 1, "Cell Loss Priority: %s",
1356         (octet & 0x01) ? "Low priority" : "High priority");
1357   ti = proto_tree_add_text(atm_tree, tvb, 4, 1, "Header Error Check: 0x%02x",
1358           tvb_get_guint8(tvb, 4));
1359   err = get_header_err(tvb_get_ptr(tvb, 0, 5));
1360   if (err == NO_ERROR_DETECTED)
1361     proto_item_append_text(ti, " (correct)");
1362   else if (err == UNCORRECTIBLE_ERROR)
1363     proto_item_append_text(ti, " (uncorrectable error)");
1364   else
1365     proto_item_append_text(ti, " (error in bit %d)", err);
1366   offset = 5;
1367
1368   switch (pinfo->pseudo_header->atm.aal) {
1369
1370   case AAL_1:
1371     if (check_col(pinfo->cinfo, COL_PROTOCOL))
1372       col_set_str(pinfo->cinfo, COL_PROTOCOL, "AAL1");
1373     ti = proto_tree_add_item(tree, proto_aal1, tvb, offset, -1, FALSE);
1374     aal_tree = proto_item_add_subtree(ti, ett_aal1);
1375     octet = tvb_get_guint8(tvb, offset);
1376     proto_tree_add_text(aal_tree, tvb, offset, 1, "CSI: %u", octet >> 7);
1377     proto_tree_add_text(aal_tree, tvb, offset, 1, "Sequence Count: %u",
1378                 (octet >> 4) & 0x7);
1379     if (check_col(pinfo->cinfo, COL_INFO)) {
1380       col_add_fstr(pinfo->cinfo, COL_INFO, "Sequence count = %u",
1381                 (octet >> 4) & 0x7);
1382     }
1383     proto_tree_add_text(aal_tree, tvb, offset, 1, "CRC: 0x%x",
1384                 (octet >> 1) & 0x7);
1385     proto_tree_add_text(aal_tree, tvb, offset, 1, "Parity: %u",
1386                 octet & 0x1);
1387     offset++;
1388
1389     proto_tree_add_text(aal_tree, tvb, offset, 47, "Payload");
1390     break;
1391
1392   case AAL_3_4:
1393     /*
1394      * XXX - or should this be the CS PDU?
1395      */
1396     if (check_col(pinfo->cinfo, COL_PROTOCOL))
1397       col_set_str(pinfo->cinfo, COL_PROTOCOL, "AAL3/4");
1398     ti = proto_tree_add_item(tree, proto_aal3_4, tvb, offset, -1, FALSE);
1399     aal_tree = proto_item_add_subtree(ti, ett_aal3_4);
1400     aal3_4_hdr = tvb_get_ntohs(tvb, offset);
1401     if (check_col(pinfo->cinfo, COL_INFO)) {
1402       col_add_fstr(pinfo->cinfo, COL_INFO, "%s, sequence number = %u",
1403                 val_to_str(aal3_4_hdr >> 14, st_vals, "Unknown (%u)"),
1404                 (aal3_4_hdr >> 10) & 0xF);
1405     }
1406     proto_tree_add_text(aal_tree, tvb, offset, 2, "Segment Type: %s",
1407                 val_to_str(aal3_4_hdr >> 14, st_vals, "Unknown (%u)"));
1408     proto_tree_add_text(aal_tree, tvb, offset, 2, "Sequence Number: %u",
1409                 (aal3_4_hdr >> 10) & 0xF);
1410     proto_tree_add_text(aal_tree, tvb, offset, 2, "Multiplex ID: %u",
1411                 aal3_4_hdr & 0x3FF);
1412     offset += 2;
1413
1414     proto_tree_add_text(aal_tree, tvb, offset, 44, "Information");
1415     offset += 44;
1416
1417     aal3_4_trlr = tvb_get_ntohs(tvb, offset);
1418     proto_tree_add_text(aal_tree, tvb, offset, 2, "Length Indicator: %u",
1419                 (aal3_4_trlr >> 10) & 0x3F);
1420     length = tvb_length_remaining(tvb, 5);
1421     crc10 = update_crc10_by_bytes(0, tvb_get_ptr(tvb, 5, length),
1422         length);
1423     proto_tree_add_text(aal_tree, tvb, offset, 2, "CRC: 0x%03x (%s)",
1424                 aal3_4_trlr & 0x3FF,
1425                 (crc10 == 0) ? "correct" : "incorrect");
1426     break;
1427
1428   case AAL_OAMCELL:
1429     if (check_col(pinfo->cinfo, COL_PROTOCOL))
1430       col_set_str(pinfo->cinfo, COL_PROTOCOL, "OAM AAL");
1431     ti = proto_tree_add_item(tree, proto_oamaal, tvb, offset, -1, FALSE);
1432     aal_tree = proto_item_add_subtree(ti, ett_oamaal);
1433     octet = tvb_get_guint8(tvb, offset);
1434     proto_tree_add_text(aal_tree, tvb, offset, 1, "OAM Type: %s",
1435                 val_to_str(octet >> 4, oam_type_vals, "Unknown (%u)"));
1436     switch (octet >> 4) {
1437
1438     case OAM_TYPE_FM:
1439       proto_tree_add_text(aal_tree, tvb, offset, 1, "Function Type: %s",
1440                 val_to_str(octet & 0x0F, ft_fm_vals, "Unknown (%u)"));
1441       break;
1442
1443     case OAM_TYPE_PM:
1444       proto_tree_add_text(aal_tree, tvb, offset, 1, "Function Type: %s",
1445                 val_to_str(octet & 0x0F, ft_pm_vals, "Unknown (%u)"));
1446       break;
1447
1448     case OAM_TYPE_AD:
1449       proto_tree_add_text(aal_tree, tvb, offset, 1, "Function Type: %s",
1450                 val_to_str(octet & 0x0F, ft_ad_vals, "Unknown (%u)"));
1451       break;
1452
1453     default:
1454       proto_tree_add_text(aal_tree, tvb, offset, 1, "Function Type: %u",
1455                 octet & 0x0F);
1456       break;
1457     }
1458     offset += 1;
1459
1460     proto_tree_add_text(aal_tree, tvb, offset, 45, "Function-specific information");
1461     offset += 45;
1462
1463     length = tvb_length_remaining(tvb, 5);
1464     crc10 = update_crc10_by_bytes(0, tvb_get_ptr(tvb, 5, length),
1465         length);
1466     oam_crc = tvb_get_ntohs(tvb, offset);
1467     proto_tree_add_text(aal_tree, tvb, offset, 2, "CRC-10: 0x%03x (%s)",
1468                 oam_crc & 0x3FF,
1469                 (crc10 == 0) ? "correct" : "incorrect");
1470     break;
1471
1472   default:
1473     next_tvb = tvb_new_subset(tvb, offset, -1, -1);
1474     call_dissector(data_handle, next_tvb, pinfo, tree);
1475     break;
1476   }
1477 }
1478
1479 static void
1480 dissect_atm_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1481     gboolean truncated)
1482 {
1483   proto_tree   *atm_tree = NULL;
1484   proto_item   *ti = NULL;
1485
1486   if (check_col(pinfo->cinfo, COL_PROTOCOL))
1487     col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATM");
1488
1489   switch (pinfo->pseudo_header->atm.channel) {
1490
1491   case 0:
1492     /* Traffic from DTE to DCE. */
1493     if (check_col(pinfo->cinfo, COL_RES_DL_DST))
1494       col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DCE");
1495     if (check_col(pinfo->cinfo, COL_RES_DL_SRC))
1496       col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DTE");
1497     break;
1498
1499   case 1:
1500     /* Traffic from DCE to DTE. */
1501     if (check_col(pinfo->cinfo, COL_RES_DL_DST))
1502       col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DTE");
1503     if (check_col(pinfo->cinfo, COL_RES_DL_SRC))
1504       col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DCE");
1505     break;
1506   }
1507
1508   if (check_col(pinfo->cinfo, COL_INFO)) {
1509     if (pinfo->pseudo_header->atm.aal == AAL_5) {
1510       col_add_fstr(pinfo->cinfo, COL_INFO, "AAL5 %s",
1511                 val_to_str(pinfo->pseudo_header->atm.type, aal5_hltype_vals,
1512                                 "Unknown traffic type (%u)"));
1513     } else {
1514       col_add_str(pinfo->cinfo, COL_INFO,
1515                 val_to_str(pinfo->pseudo_header->atm.aal, aal_vals,
1516                         "Unknown AAL (%u)"));
1517     }
1518   }
1519
1520   if (tree) {
1521     ti = proto_tree_add_protocol_format(tree, proto_atm, tvb, 0, 0, "ATM");
1522     atm_tree = proto_item_add_subtree(ti, ett_atm);
1523
1524     switch (pinfo->pseudo_header->atm.channel) {
1525
1526     case 0:
1527       /* Traffic from DTE to DCE. */
1528       proto_tree_add_text(atm_tree, tvb, 0, 0, "Channel: DTE->DCE");
1529       break;
1530
1531     case 1:
1532       /* Traffic from DCE to DTE. */
1533       proto_tree_add_text(atm_tree, tvb, 0, 0, "Channel: DCE->DTE");
1534       break;
1535
1536     default:
1537       /* Sniffers shouldn't provide anything other than 0 or 1. */
1538       proto_tree_add_text(atm_tree, tvb, 0, 0, "Channel: %u",
1539                 pinfo->pseudo_header->atm.channel);
1540       break;
1541     }
1542
1543     proto_tree_add_uint_format(atm_tree, hf_atm_aal, tvb, 0, 0,
1544         pinfo->pseudo_header->atm.aal,
1545         "AAL: %s",
1546         val_to_str(pinfo->pseudo_header->atm.aal, aal_vals,
1547           "Unknown AAL (%u)"));
1548   }
1549   if (pinfo->pseudo_header->atm.flags & ATM_RAW_CELL) {
1550     /* This is a single cell, with the cell header at the beginning. */
1551     proto_item_set_len(ti, 5);
1552     dissect_atm_cell(tvb, pinfo, tree, atm_tree);
1553   } else {
1554     /* This is a reassembled PDU. */
1555     dissect_reassembled_pdu(tvb, pinfo, tree, atm_tree, truncated);
1556   }
1557 }
1558
1559 static void
1560 dissect_atm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1561 {
1562   dissect_atm_common(tvb, pinfo, tree, TRUE);
1563 }
1564
1565 static void
1566 dissect_atm_untruncated(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1567 {
1568   dissect_atm_common(tvb, pinfo, tree, FALSE);
1569 }
1570
1571 void
1572 proto_register_atm(void)
1573 {
1574         static hf_register_info hf[] = {
1575                 { &hf_atm_aal,
1576                 { "AAL",                "atm.aal", FT_UINT8, BASE_DEC, VALS(aal_vals), 0x0,
1577                         "", HFILL }},
1578
1579                 { &hf_atm_vpi,
1580                 { "VPI",                "atm.vpi", FT_UINT8, BASE_DEC, NULL, 0x0,
1581                         "", HFILL }},
1582
1583                 { &hf_atm_vci,
1584                 { "VCI",                "atm.vci", FT_UINT16, BASE_DEC, NULL, 0x0,
1585                         "", HFILL }},
1586         };
1587         static gint *ett[] = {
1588                 &ett_atm,
1589                 &ett_ilmi,
1590                 &ett_aal1,
1591                 &ett_aal3_4,
1592                 &ett_oamaal,
1593                 &ett_atm_lane,
1594                 &ett_atm_lane_lc_lan_dest,
1595                 &ett_atm_lane_lc_lan_dest_rd,
1596                 &ett_atm_lane_lc_flags,
1597                 &ett_atm_lane_lc_tlv,
1598         };
1599         proto_atm = proto_register_protocol("ATM", "ATM", "atm");
1600         proto_aal1 = proto_register_protocol("ATM AAL1", "AAL1", "aal1");
1601         proto_aal3_4 = proto_register_protocol("ATM AAL3/4", "AAL3_4", "aal3_4");
1602         proto_oamaal = proto_register_protocol("ATM OAM AAL", "OAM AAL", "oamaal");
1603         proto_register_field_array(proto_atm, hf, array_length(hf));
1604         proto_register_subtree_array(ett, array_length(ett));
1605
1606         proto_ilmi = proto_register_protocol("ILMI", "ILMI", "ilmi");
1607
1608         register_dissector("ilmi", dissect_ilmi, proto_ilmi);
1609
1610         proto_atm_lane = proto_register_protocol("ATM LAN Emulation",
1611             "ATM LANE", "lane");
1612
1613         register_dissector("lane", dissect_lane, proto_atm_lane);
1614 }
1615
1616 void
1617 proto_reg_handoff_atm(void)
1618 {
1619         dissector_handle_t atm_handle, atm_untruncated_handle;
1620
1621         /*
1622          * Get handles for the Ethernet, Token Ring, LLC, SSCOP, LANE,
1623          * and ILMI dissectors.
1624          */
1625         eth_handle = find_dissector("eth");
1626         tr_handle = find_dissector("tr");
1627         llc_handle = find_dissector("llc");
1628         sscop_handle = find_dissector("sscop");
1629         lane_handle = find_dissector("lane");
1630         ilmi_handle = find_dissector("ilmi");
1631         data_handle = find_dissector("data");
1632
1633         atm_handle = create_dissector_handle(dissect_atm, proto_atm);
1634         dissector_add("wtap_encap", WTAP_ENCAP_ATM_PDUS, atm_handle);
1635
1636         atm_untruncated_handle = create_dissector_handle(dissect_atm_untruncated,
1637             proto_atm);
1638         dissector_add("wtap_encap", WTAP_ENCAP_ATM_PDUS_UNTRUNCATED,
1639             atm_untruncated_handle);
1640 }