2 * Routines for ATM packet disassembly
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
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.
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.
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.
31 #include <epan/packet.h>
33 #include <epan/addr_resolv.h>
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"
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;
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;
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;
76 * http://www.atmforum.org/atmforum/specs/approved.html
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.
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
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" },
124 /* LE Control statuses */
125 static const value_string le_control_status_vals[] = {
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" },
143 /* LE Control LAN destination tags */
144 #define TAG_NOT_PRESENT 0x0000
145 #define TAG_MAC_ADDRESS 0x0001
146 #define TAG_ROUTE_DESCRIPTOR 0x0002
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" },
155 /* LE Control LAN types */
156 #define LANT_UNSPEC 0x00
157 #define LANT_802_3 0x01
158 #define LANT_802_5 0x02
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" },
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" },
177 dissect_le_client(tvbuff_t *tvb, proto_tree *tree)
180 proto_tree *lane_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);
186 proto_tree_add_text(lane_tree, tvb, 0, 2, "LE Client: 0x%04X",
187 tvb_get_ntohs(tvb, 0));
192 dissect_lan_destination(tvbuff_t *tvb, int offset, const char *type, proto_tree *tree)
195 proto_tree *dest_tree;
199 guint16 route_descriptor;
201 td = proto_tree_add_text(tree, tvb, offset, 8, "%s LAN destination",
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)"));
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)));
217 case TAG_ROUTE_DESCRIPTOR:
219 route_descriptor = tvb_get_ntohs(tvb, offset);
220 trd = proto_tree_add_text(dest_tree, tvb, offset, 2, "Route descriptor: 0x%02X",
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,
226 proto_tree_add_text(rd_tree, tvb, offset, 2,
227 decode_numeric_bitfield(route_descriptor, 0x000F, 2*8,
228 "Bridge number = %u"));
234 * TLV values in LE Control frames.
236 #define TLV_TYPE(oui, ident) (((oui) << 8) | (ident))
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)
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" },
288 dissect_le_control_tlvs(tvbuff_t *tvb, int offset, guint num_tlvs,
294 proto_tree *tlv_tree;
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;
311 dissect_le_configure_join_frame(tvbuff_t *tvb, int offset, proto_tree *tree)
316 dissect_lan_destination(tvb, offset, "Source", tree);
319 dissect_lan_destination(tvb, offset, "Target", tree);
322 proto_tree_add_text(tree, tvb, offset, 20, "Source ATM Address: %s",
323 tvb_bytes_to_str(tvb, offset, 20));
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)"));
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)"));
336 num_tlvs = tvb_get_guint8(tvb, offset);
337 proto_tree_add_text(tree, tvb, offset, 1, "Number of TLVs: %u", num_tlvs);
340 name_size = tvb_get_guint8(tvb, offset);
341 proto_tree_add_text(tree, tvb, offset, 1, "ELAN name size: %u", name_size);
344 proto_tree_add_text(tree, tvb, offset, 20, "Target ATM Address: %s",
345 tvb_bytes_to_str(tvb, offset, 20));
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));
356 dissect_le_control_tlvs(tvb, offset, num_tlvs, tree);
360 dissect_le_registration_frame(tvbuff_t *tvb, int offset, proto_tree *tree)
364 dissect_lan_destination(tvb, offset, "Source", tree);
367 dissect_lan_destination(tvb, offset, "Target", tree);
370 proto_tree_add_text(tree, tvb, offset, 20, "Source ATM Address: %s",
371 tvb_bytes_to_str(tvb, offset, 20));
377 num_tlvs = tvb_get_guint8(tvb, offset);
378 proto_tree_add_text(tree, tvb, offset, 1, "Number of TLVs: %u", num_tlvs);
384 dissect_le_control_tlvs(tvb, offset, num_tlvs, tree);
388 dissect_le_arp_frame(tvbuff_t *tvb, int offset, proto_tree *tree)
392 dissect_lan_destination(tvb, offset, "Source", tree);
395 dissect_lan_destination(tvb, offset, "Target", tree);
398 proto_tree_add_text(tree, tvb, offset, 20, "Source ATM Address: %s",
399 tvb_bytes_to_str(tvb, offset, 20));
405 num_tlvs = tvb_get_guint8(tvb, offset);
406 proto_tree_add_text(tree, tvb, offset, 1, "Number of TLVs: %u", num_tlvs);
412 proto_tree_add_text(tree, tvb, offset, 20, "Target ATM Address: %s",
413 tvb_bytes_to_str(tvb, offset, 20));
419 dissect_le_control_tlvs(tvb, offset, num_tlvs, tree);
423 dissect_le_verify_frame(tvbuff_t *tvb, int offset, proto_tree *tree)
430 num_tlvs = tvb_get_guint8(tvb, offset);
431 proto_tree_add_text(tree, tvb, offset, 1, "Number of TLVs: %u", num_tlvs);
437 proto_tree_add_text(tree, tvb, offset, 20, "Target ATM Address: %s",
438 tvb_bytes_to_str(tvb, offset, 20));
444 dissect_le_control_tlvs(tvb, offset, num_tlvs, tree);
448 dissect_le_flush_frame(tvbuff_t *tvb, int offset, proto_tree *tree)
450 dissect_lan_destination(tvb, offset, "Source", tree);
453 dissect_lan_destination(tvb, offset, "Target", tree);
456 proto_tree_add_text(tree, tvb, offset, 20, "Source ATM Address: %s",
457 tvb_bytes_to_str(tvb, offset, 20));
463 proto_tree_add_text(tree, tvb, offset, 20, "Target ATM Address: %s",
464 tvb_bytes_to_str(tvb, offset, 20));
472 dissect_le_control(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
475 proto_tree *lane_tree = NULL;
478 proto_tree *flags_tree;
482 if (check_col(pinfo->cinfo, COL_INFO))
483 col_set_str(pinfo->cinfo, COL_INFO, "LE Control");
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);
489 proto_tree_add_text(lane_tree, tvb, offset, 2, "Marker: 0x%04X",
490 tvb_get_ntohs(tvb, offset));
495 proto_tree_add_text(lane_tree, tvb, offset, 1, "Protocol: 0x%02X",
496 tvb_get_guint8(tvb, offset));
501 proto_tree_add_text(lane_tree, tvb, offset, 1, "Version: 0x%02X",
502 tvb_get_guint8(tvb, offset));
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)"));
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)"));
519 if (opcode == READY_QUERY || opcode == READY_IND) {
520 /* There's nothing more in this packet. */
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)"));
533 proto_tree_add_text(lane_tree, tvb, offset, 4, "Transaction ID: 0x%08X",
534 tvb_get_ntohl(tvb, offset));
537 proto_tree_add_text(lane_tree, tvb, offset, 2, "Requester LECID: 0x%04X",
538 tvb_get_ntohs(tvb, offset));
541 flags = tvb_get_ntohs(tvb, offset);
542 tf = proto_tree_add_text(lane_tree, tvb, offset, 2, "Flags: 0x%04X",
544 flags_tree = proto_item_add_subtree(tf, ett_atm_lane_lc_flags);
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"));
554 dissect_le_configure_join_frame(tvb, offset, lane_tree);
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"));
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"));
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"));
579 dissect_le_configure_join_frame(tvb, offset, lane_tree);
582 case LE_REGISTER_REQUEST:
583 case LE_REGISTER_RESPONSE:
584 case LE_UNREGISTER_REQUEST:
585 case LE_UNREGISTER_RESPONSE:
587 dissect_le_registration_frame(tvb, offset, lane_tree);
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"));
599 dissect_le_arp_frame(tvb, offset, lane_tree);
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"));
607 /* 92 reserved bytes */
610 case LE_VERIFY_REQUEST:
611 case LE_VERIFY_RESPONSE:
613 dissect_le_verify_frame(tvb, offset, lane_tree);
616 case LE_FLUSH_REQUEST:
617 case LE_FLUSH_RESPONSE:
619 dissect_le_flush_frame(tvb, offset, lane_tree);
626 capture_lane(const union wtap_pseudo_header *pseudo_header, const guchar *pd,
627 int len, packet_counts *ld)
629 /* Is it LE Control, 802.3, 802.5, or "none of the above"? */
630 switch (pseudo_header->atm.subtype) {
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);
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);
651 dissect_lane(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
654 tvbuff_t *next_tvb_le_client;
656 if (check_col(pinfo->cinfo, COL_PROTOCOL))
657 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATM LANE");
659 /* Is it LE Control, 802.3, 802.5, or "none of the above"? */
660 switch (pinfo->pseudo_header->atm.subtype) {
662 case TRAF_ST_LANE_LE_CTRL:
663 dissect_le_control(tvb, pinfo, tree);
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);
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);
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);
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);
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);
699 dissect_ilmi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
701 dissect_snmp_pdu(tvb, 0, pinfo, tree, proto_ilmi, ett_ilmi, FALSE);
705 static const value_string aal_vals[] = {
706 { AAL_UNKNOWN, "Unknown AAL" },
709 { AAL_3_4, "AAL3/4" },
711 { AAL_USER, "User AAL" },
712 { AAL_SIGNALLING, "Signalling AAL" },
713 { AAL_OAMCELL, "OAM cell" },
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" },
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" },
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" },
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" },
769 capture_atm(const union wtap_pseudo_header *pseudo_header, const guchar *pd,
770 int len, packet_counts *ld)
772 if (pseudo_header->atm.aal == AAL_5) {
773 switch (pseudo_header->atm.type) {
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);
783 capture_lane(pseudo_header, pd, len, ld);
795 * Charles Michael Heard's CRC-32 code, from
797 * http://cell-relay.indiana.edu/cell-relay/publications/software/CRC/32bitCRC.c.html
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.
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 */
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. */
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. */
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. */
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). */
835 /* The table lookup technique was adapted from the algorithm described */
836 /* by Avram Perez, Byte-wise CRC Calculations, IEEE Micro 3, 40 (1983).*/
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,
906 update_crc(guint32 crc_accum, const guint8 *data_blk_ptr, int data_blk_size)
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];
919 dissect_reassembled_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
921 proto_tree *atm_tree, gboolean truncated)
923 guint length, reported_length;
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.
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) {
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)"));
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)"));
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)"));
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);
965 /* Also show vpi/vci in info column */
966 if (check_col(pinfo->cinfo, COL_INFO))
968 col_append_fstr(pinfo->cinfo, COL_INFO, " VPI=%u, VCI=%u",
969 pinfo->pseudo_header->atm.vpi,
970 pinfo->pseudo_header->atm.vci);
977 * The packet data does not include stuff such as the AAL5
980 if (pinfo->pseudo_header->atm.cells != 0) {
982 * If the cell count is 0, assume it means we don't know how
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.
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);
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.
1010 length = tvb_length(tvb);
1011 reported_length = tvb_reported_length(tvb);
1012 if ((reported_length % 48) == 0) {
1014 * Reported length is a multiple of 48, so we can presumably
1015 * divide it by 48 to get the number of cells.
1017 proto_tree_add_text(atm_tree, tvb, 0, 0, "Cells: %u",
1018 reported_length/48);
1020 if (pinfo->pseudo_header->atm.aal == AAL_5 &&
1021 length >= reported_length) {
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
1028 aal5_length = tvb_get_ntohs(tvb, length - 6);
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.
1035 * If it's not sane, assume we don't have a trailer.
1037 if (aal5_length > 0 && aal5_length <= length - 8) {
1039 * How much padding is there?
1041 pad_length = length - aal5_length - 8;
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
1051 * If there's more than 47 bytes of padding, assume we don't
1054 if (pad_length <= 47) {
1056 if (pad_length > 0) {
1057 proto_tree_add_text(atm_tree, tvb, aal5_length, pad_length,
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",
1066 crc = tvb_get_ntohl(tvb, length - 4);
1067 calc_crc = update_crc(0xFFFFFFFF, tvb_get_ptr(tvb, 0, 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");
1073 next_tvb = tvb_new_subset(tvb, 0, aal5_length, aal5_length);
1079 switch (pinfo->pseudo_header->atm.aal) {
1081 case AAL_SIGNALLING:
1082 call_dissector(sscop_handle, next_tvb, pinfo, tree);
1086 switch (pinfo->pseudo_header->atm.type) {
1089 call_dissector(fr_handle, next_tvb, pinfo, tree);
1093 call_dissector(llc_handle, next_tvb, pinfo, tree);
1097 call_dissector(lane_handle, next_tvb, pinfo, tree);
1101 call_dissector(ilmi_handle, next_tvb, pinfo, tree);
1106 /* Dump it as raw data. */
1107 call_dissector(data_handle, next_tvb, pinfo, tree);
1114 switch (pinfo->pseudo_header->atm.type) {
1116 /* Skip first 4 bytes of message
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);
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);
1136 /* Dump it as raw data. */
1137 call_dissector(data_handle, next_tvb, pinfo, tree);
1145 /* Dump it as raw data. */
1146 call_dissector(data_handle, next_tvb, pinfo, tree);
1153 * Charles Michael Heard's HEC code, from
1155 * http://cell-relay.indiana.edu/cell-relay/publications/software/CRC/32bitCRC.tutorial.html
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.
1163 #define COSET_LEADER 0x055 /* x^6 + x^4 + x^2 + 1 */
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,
1200 #define NO_ERROR_DETECTED -128
1201 #define UNCORRECTIBLE_ERROR 128
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,
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.
1243 get_header_err(const guint8 *cell_header)
1245 register guint8 syndrome;
1246 register int i, err_posn;
1249 for (i = 0; i < 4; i++)
1250 syndrome = syndrome_table[syndrome ^ cell_header[i]];
1251 syndrome ^= cell_header[4] ^ COSET_LEADER;
1253 err_posn = err_posn_table [syndrome];
1256 return NO_ERROR_DETECTED;
1257 else if (err_posn < 40)
1260 return UNCORRECTIBLE_ERROR;
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" },
1274 * Charles Michael Heard's CRC-10 code, from
1276 * http://cell-relay.indiana.edu/cell-relay/publications/software/CRC/crc10.html
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.
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,
1317 /* update the data block's CRC-10 remainder one byte at a time */
1319 update_crc10_by_bytes(guint16 crc10_accum, const guint8 *data_blk_ptr,
1324 for (i = 0; i < data_blk_size; i++) {
1325 crc10_accum = ((crc10_accum << 8) & 0x3ff)
1326 ^ byte_crc10_table[( crc10_accum >> 2) & 0xff]
1332 static const value_string st_vals[] = {
1340 #define OAM_TYPE_FM 1 /* Fault Management */
1341 #define OAM_TYPE_PM 2 /* Performance Management */
1342 #define OAM_TYPE_AD 8 /* Activation/Deactivation */
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" },
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" },
1359 static const value_string ft_pm_vals[] = {
1360 { 0, "Forward Monitoring" },
1361 { 1, "Backward Reporting" },
1362 { 2, "Monitoring and Reporting" },
1366 static const value_string ft_ad_vals[] = {
1367 { 0, "Performance Monitoring" },
1368 { 1, "Continuity Check" },
1373 dissect_atm_cell(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1374 proto_tree *atm_tree)
1377 proto_tree *aal_tree;
1385 guint16 aal3_4_hdr, aal3_4_trlr;
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);
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);
1400 octet = tvb_get_guint8(tvb, 3);
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)");
1416 proto_item_append_text(ti, " (error in bit %d)", err);
1420 * Check for OAM cells.
1421 * XXX - do this for all AAL values, overriding whatever information
1422 * Wiretap got from the file?
1424 aal = pinfo->pseudo_header->atm.aal;
1425 if (aal == AAL_USER) {
1427 * OAM F4 is VCI 3 or 4 and PT 0X0.
1430 if (((vci == 3 || vci == 4) && ((pt & 0x5) == 0)) ||
1431 ((pt & 0x6) == 0x4))
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);
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",
1458 proto_tree_add_text(aal_tree, tvb, offset, 47, "Payload");
1463 * XXX - or should this be the CS PDU?
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);
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);
1485 proto_tree_add_text(aal_tree, tvb, offset, 44, "Information");
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),
1494 proto_tree_add_text(aal_tree, tvb, offset, 2, "CRC: 0x%03x (%s)",
1495 aal3_4_trlr & 0x3FF,
1496 (crc10 == 0) ? "correct" : "incorrect");
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) {
1515 proto_tree_add_text(aal_tree, tvb, offset, 1, "Function Type: %s",
1516 val_to_str(octet & 0x0F, ft_fm_vals, "Unknown (%u)"));
1520 proto_tree_add_text(aal_tree, tvb, offset, 1, "Function Type: %s",
1521 val_to_str(octet & 0x0F, ft_pm_vals, "Unknown (%u)"));
1525 proto_tree_add_text(aal_tree, tvb, offset, 1, "Function Type: %s",
1526 val_to_str(octet & 0x0F, ft_ad_vals, "Unknown (%u)"));
1530 proto_tree_add_text(aal_tree, tvb, offset, 1, "Function Type: %u",
1536 proto_tree_add_text(aal_tree, tvb, offset, 45, "Function-specific information");
1539 length = tvb_length_remaining(tvb, 5);
1540 crc10 = update_crc10_by_bytes(0, tvb_get_ptr(tvb, 5, length),
1542 oam_crc = tvb_get_ntohs(tvb, offset);
1543 proto_tree_add_text(aal_tree, tvb, offset, 2, "CRC-10: 0x%03x (%s)",
1545 (crc10 == 0) ? "correct" : "incorrect");
1549 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
1550 call_dissector(data_handle, next_tvb, pinfo, tree);
1556 dissect_atm_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1559 proto_tree *atm_tree = NULL;
1560 proto_item *atm_ti = NULL;
1562 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1563 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATM");
1565 switch (pinfo->pseudo_header->atm.channel) {
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");
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");
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)"));
1590 col_add_str(pinfo->cinfo, COL_INFO,
1591 val_to_str(pinfo->pseudo_header->atm.aal, aal_vals,
1592 "Unknown AAL (%u)"));
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);
1600 switch (pinfo->pseudo_header->atm.channel) {
1603 /* Traffic from DTE to DCE. */
1604 proto_tree_add_text(atm_tree, tvb, 0, 0, "Channel: DTE->DCE");
1608 /* Traffic from DCE to DTE. */
1609 proto_tree_add_text(atm_tree, tvb, 0, 0, "Channel: DCE->DTE");
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);
1619 proto_tree_add_uint_format_value(atm_tree, hf_atm_aal, tvb, 0, 0,
1620 pinfo->pseudo_header->atm.aal,
1622 val_to_str(pinfo->pseudo_header->atm.aal, aal_vals,
1623 "Unknown AAL (%u)"));
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);
1630 /* This is a reassembled PDU. */
1631 dissect_reassembled_pdu(tvb, pinfo, tree, atm_tree, atm_ti, truncated);
1636 dissect_atm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1638 dissect_atm_common(tvb, pinfo, tree, TRUE);
1642 dissect_atm_untruncated(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1644 dissect_atm_common(tvb, pinfo, tree, FALSE);
1648 proto_register_atm(void)
1650 static hf_register_info hf[] = {
1652 { "AAL", "atm.aal", FT_UINT8, BASE_DEC, VALS(aal_vals), 0x0,
1656 { "VPI", "atm.vpi", FT_UINT8, BASE_DEC, NULL, 0x0,
1660 { "VCI", "atm.vci", FT_UINT16, BASE_DEC, NULL, 0x0,
1664 { "CID", "atm.cid", FT_UINT8, BASE_DEC, NULL, 0x0,
1668 static gint *ett[] = {
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,
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));
1687 proto_ilmi = proto_register_protocol("ILMI", "ILMI", "ilmi");
1689 register_dissector("ilmi", dissect_ilmi, proto_ilmi);
1691 proto_atm_lane = proto_register_protocol("ATM LAN Emulation",
1692 "ATM LANE", "lane");
1694 register_dissector("lane", dissect_lane, proto_atm_lane);
1695 register_dissector("atm_untruncated", dissect_atm_untruncated, proto_atm);
1699 proto_reg_handoff_atm(void)
1701 dissector_handle_t atm_handle, atm_untruncated_handle;
1704 * Get handles for the Ethernet, Token Ring, Frame Relay, LLC,
1705 * SSCOP, LANE, and ILMI dissectors.
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");
1717 atm_handle = create_dissector_handle(dissect_atm, proto_atm);
1718 dissector_add("wtap_encap", WTAP_ENCAP_ATM_PDUS, atm_handle);
1720 atm_untruncated_handle = create_dissector_handle(dissect_atm_untruncated,
1722 dissector_add("wtap_encap", WTAP_ENCAP_ATM_PDUS_UNTRUNCATED,
1723 atm_untruncated_handle);