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