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