2 * Routines for ATM packet disassembly
4 * $Id: packet-atm.c,v 1.57 2003/01/10 04:04:39 guy Exp $
6 * Ethereal - Network traffic analyzer
7 * By Gerald Combs <gerald@ethereal.com>
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/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 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;
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;
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;
73 * http://www.atmforum.org/atmforum/specs/approved.html
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.
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
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" },
121 /* LE Control statuses */
122 static const value_string le_control_status_vals[] = {
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" },
140 /* LE Control LAN destination tags */
141 #define TAG_NOT_PRESENT 0x0000
142 #define TAG_MAC_ADDRESS 0x0001
143 #define TAG_ROUTE_DESCRIPTOR 0x0002
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" },
152 /* LE Control LAN types */
153 #define LANT_UNSPEC 0x00
154 #define LANT_802_3 0x01
155 #define LANT_802_5 0x02
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" },
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" },
174 dissect_le_client(tvbuff_t *tvb, proto_tree *tree)
177 proto_tree *lane_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);
183 proto_tree_add_text(lane_tree, tvb, 0, 2, "LE Client: 0x%04X",
184 tvb_get_ntohs(tvb, 0));
189 dissect_lan_destination(tvbuff_t *tvb, int offset, const char *type, proto_tree *tree)
192 proto_tree *dest_tree;
196 guint16 route_descriptor;
198 td = proto_tree_add_text(tree, tvb, offset, 8, "%s LAN destination",
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)"));
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)));
214 case TAG_ROUTE_DESCRIPTOR:
216 route_descriptor = tvb_get_ntohs(tvb, offset);
217 trd = proto_tree_add_text(dest_tree, tvb, offset, 2, "Route descriptor: 0x%02X",
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,
223 proto_tree_add_text(rd_tree, tvb, offset, 2,
224 decode_numeric_bitfield(route_descriptor, 0x000F, 2*8,
225 "Bridge number = %u"));
231 * TLV values in LE Control frames.
233 #define TLV_TYPE(oui, ident) (((oui) << 8) | (ident))
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)
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" },
285 dissect_le_control_tlvs(tvbuff_t *tvb, int offset, guint num_tlvs,
291 proto_tree *tlv_tree;
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;
308 dissect_le_configure_join_frame(tvbuff_t *tvb, int offset, proto_tree *tree)
313 dissect_lan_destination(tvb, offset, "Source", tree);
316 dissect_lan_destination(tvb, offset, "Target", tree);
319 proto_tree_add_text(tree, tvb, offset, 20, "Source ATM Address: %s",
320 tvb_bytes_to_str(tvb, offset, 20));
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)"));
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)"));
333 num_tlvs = tvb_get_guint8(tvb, offset);
334 proto_tree_add_text(tree, tvb, offset, 1, "Number of TLVs: %u", num_tlvs);
337 name_size = tvb_get_guint8(tvb, offset);
338 proto_tree_add_text(tree, tvb, offset, 1, "ELAN name size: %u", name_size);
341 proto_tree_add_text(tree, tvb, offset, 20, "Target ATM Address: %s",
342 tvb_bytes_to_str(tvb, offset, 20));
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));
353 dissect_le_control_tlvs(tvb, offset, num_tlvs, tree);
357 dissect_le_registration_frame(tvbuff_t *tvb, int offset, proto_tree *tree)
361 dissect_lan_destination(tvb, offset, "Source", tree);
364 dissect_lan_destination(tvb, offset, "Target", tree);
367 proto_tree_add_text(tree, tvb, offset, 20, "Source ATM Address: %s",
368 tvb_bytes_to_str(tvb, offset, 20));
374 num_tlvs = tvb_get_guint8(tvb, offset);
375 proto_tree_add_text(tree, tvb, offset, 1, "Number of TLVs: %u", num_tlvs);
381 dissect_le_control_tlvs(tvb, offset, num_tlvs, tree);
385 dissect_le_arp_frame(tvbuff_t *tvb, int offset, proto_tree *tree)
389 dissect_lan_destination(tvb, offset, "Source", tree);
392 dissect_lan_destination(tvb, offset, "Target", tree);
395 proto_tree_add_text(tree, tvb, offset, 20, "Source ATM Address: %s",
396 tvb_bytes_to_str(tvb, offset, 20));
402 num_tlvs = tvb_get_guint8(tvb, offset);
403 proto_tree_add_text(tree, tvb, offset, 1, "Number of TLVs: %u", num_tlvs);
409 proto_tree_add_text(tree, tvb, offset, 20, "Target ATM Address: %s",
410 tvb_bytes_to_str(tvb, offset, 20));
416 dissect_le_control_tlvs(tvb, offset, num_tlvs, tree);
420 dissect_le_verify_frame(tvbuff_t *tvb, int offset, proto_tree *tree)
427 num_tlvs = tvb_get_guint8(tvb, offset);
428 proto_tree_add_text(tree, tvb, offset, 1, "Number of TLVs: %u", num_tlvs);
434 proto_tree_add_text(tree, tvb, offset, 20, "Target ATM Address: %s",
435 tvb_bytes_to_str(tvb, offset, 20));
441 dissect_le_control_tlvs(tvb, offset, num_tlvs, tree);
445 dissect_le_flush_frame(tvbuff_t *tvb, int offset, proto_tree *tree)
447 dissect_lan_destination(tvb, offset, "Source", tree);
450 dissect_lan_destination(tvb, offset, "Target", tree);
453 proto_tree_add_text(tree, tvb, offset, 20, "Source ATM Address: %s",
454 tvb_bytes_to_str(tvb, offset, 20));
460 proto_tree_add_text(tree, tvb, offset, 20, "Target ATM Address: %s",
461 tvb_bytes_to_str(tvb, offset, 20));
469 dissect_le_control(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
472 proto_tree *lane_tree = NULL;
475 proto_tree *flags_tree;
479 if (check_col(pinfo->cinfo, COL_INFO))
480 col_set_str(pinfo->cinfo, COL_INFO, "LE Control");
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);
486 proto_tree_add_text(lane_tree, tvb, offset, 2, "Marker: 0x%04X",
487 tvb_get_ntohs(tvb, offset));
492 proto_tree_add_text(lane_tree, tvb, offset, 1, "Protocol: 0x%02X",
493 tvb_get_guint8(tvb, offset));
498 proto_tree_add_text(lane_tree, tvb, offset, 1, "Version: 0x%02X",
499 tvb_get_guint8(tvb, offset));
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)"));
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)"));
516 if (opcode == READY_QUERY || opcode == READY_IND) {
517 /* There's nothing more in this packet. */
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)"));
530 proto_tree_add_text(lane_tree, tvb, offset, 4, "Transaction ID: 0x%08X",
531 tvb_get_ntohl(tvb, offset));
534 proto_tree_add_text(lane_tree, tvb, offset, 2, "Requester LECID: 0x%04X",
535 tvb_get_ntohs(tvb, offset));
538 flags = tvb_get_ntohs(tvb, offset);
539 tf = proto_tree_add_text(lane_tree, tvb, offset, 2, "Flags: 0x%04X",
541 flags_tree = proto_item_add_subtree(tf, ett_atm_lane_lc_flags);
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"));
551 dissect_le_configure_join_frame(tvb, offset, lane_tree);
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"));
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"));
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"));
576 dissect_le_configure_join_frame(tvb, offset, lane_tree);
579 case LE_REGISTER_REQUEST:
580 case LE_REGISTER_RESPONSE:
581 case LE_UNREGISTER_REQUEST:
582 case LE_UNREGISTER_RESPONSE:
584 dissect_le_registration_frame(tvb, offset, lane_tree);
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"));
596 dissect_le_arp_frame(tvb, offset, lane_tree);
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"));
604 /* 92 reserved bytes */
607 case LE_VERIFY_REQUEST:
608 case LE_VERIFY_RESPONSE:
610 dissect_le_verify_frame(tvb, offset, lane_tree);
613 case LE_FLUSH_REQUEST:
614 case LE_FLUSH_RESPONSE:
616 dissect_le_flush_frame(tvb, offset, lane_tree);
623 capture_lane(const union wtap_pseudo_header *pseudo_header, const guchar *pd,
624 int len, packet_counts *ld)
626 /* Is it LE Control, 802.3, 802.5, or "none of the above"? */
627 switch (pseudo_header->atm.subtype) {
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);
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);
648 dissect_lane(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
651 tvbuff_t *next_tvb_le_client;
653 if (check_col(pinfo->cinfo, COL_PROTOCOL))
654 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATM LANE");
656 /* Is it LE Control, 802.3, 802.5, or "none of the above"? */
657 switch (pinfo->pseudo_header->atm.subtype) {
659 case TRAF_ST_LANE_LE_CTRL:
660 dissect_le_control(tvb, pinfo, tree);
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);
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);
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);
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);
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);
696 dissect_ilmi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
698 dissect_snmp_pdu(tvb, 0, pinfo, tree, "ILMI", proto_ilmi, ett_ilmi);
702 static const value_string aal_vals[] = {
703 { AAL_UNKNOWN, "Unknown AAL" },
706 { AAL_3_4, "AAL3/4" },
708 { AAL_USER, "User AAL" },
709 { AAL_SIGNALLING, "Signalling AAL" },
710 { AAL_OAMCELL, "OAM cell" },
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" },
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" },
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" },
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" },
766 capture_atm(const union wtap_pseudo_header *pseudo_header, const guchar *pd,
767 int len, packet_counts *ld)
769 if (pseudo_header->atm.aal == AAL_5) {
770 switch (pseudo_header->atm.type) {
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);
780 capture_lane(pseudo_header, pd, len, ld);
792 * Charles Michael Heard's CRC-32 code, from
794 * http://cell-relay.indiana.edu/cell-relay/publications/software/CRC/32bitCRC.c.html
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.
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 */
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. */
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. */
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. */
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). */
832 /* The table lookup technique was adapted from the algorithm described */
833 /* by Avram Perez, Byte-wise CRC Calculations, IEEE Micro 3, 40 (1983).*/
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,
903 update_crc(guint32 crc_accum, const guint8 *data_blk_ptr, int data_blk_size)
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];
916 dissect_reassembled_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
917 proto_tree *atm_tree, gboolean truncated)
919 guint length, reported_length;
927 * This is reassembled traffic, so the cell headers are missing;
928 * show the VPI and VCI from the pseudo-header.
930 proto_tree_add_uint(atm_tree, hf_atm_vpi, tvb, 0, 0,
931 pinfo->pseudo_header->atm.vpi);
932 proto_tree_add_uint(atm_tree, hf_atm_vci, tvb, 0, 0,
933 pinfo->pseudo_header->atm.vci);
934 if (pinfo->pseudo_header->atm.aal == AAL_5) {
935 proto_tree_add_text(atm_tree, tvb, 0, 0, "Traffic type: %s",
936 val_to_str(pinfo->pseudo_header->atm.type, aal5_hltype_vals,
937 "Unknown AAL5 traffic type (%u)"));
938 switch (pinfo->pseudo_header->atm.type) {
941 proto_tree_add_text(atm_tree, tvb, 0, 0, "VC multiplexed traffic type: %s",
942 val_to_str(pinfo->pseudo_header->atm.subtype,
943 vcmx_type_vals, "Unknown VCMX traffic type (%u)"));
947 proto_tree_add_text(atm_tree, tvb, 0, 0, "LANE traffic type: %s",
948 val_to_str(pinfo->pseudo_header->atm.subtype,
949 lane_type_vals, "Unknown LANE traffic type (%u)"));
953 proto_tree_add_text(atm_tree, tvb, 0, 0, "Ipsilon traffic type: %s",
954 val_to_str(pinfo->pseudo_header->atm.subtype,
955 ipsilon_type_vals, "Unknown Ipsilon traffic type (%u)"));
963 * The packet data does not include stuff such as the AAL5
966 if (pinfo->pseudo_header->atm.cells != 0) {
968 * If the cell count is 0, assume it means we don't know how
971 * XXX - also assume it means we don't know what was in the AAL5
972 * trailer. We may, however, find some capture program that can
973 * give us the AAL5 trailer information but not the cell count,
974 * in which case we need some other way of indicating whether we
975 * have the AAL5 trailer information.
978 proto_tree_add_text(atm_tree, tvb, 0, 0, "Cells: %u",
979 pinfo->pseudo_header->atm.cells);
980 proto_tree_add_text(atm_tree, tvb, 0, 0, "AAL5 UU: 0x%02x",
981 pinfo->pseudo_header->atm.aal5t_u2u >> 8);
982 proto_tree_add_text(atm_tree, tvb, 0, 0, "AAL5 CPI: 0x%02x",
983 pinfo->pseudo_header->atm.aal5t_u2u & 0xFF);
984 proto_tree_add_text(atm_tree, tvb, 0, 0, "AAL5 len: %u",
985 pinfo->pseudo_header->atm.aal5t_len);
986 proto_tree_add_text(atm_tree, tvb, 0, 0, "AAL5 CRC: 0x%08X",
987 pinfo->pseudo_header->atm.aal5t_chksum);
992 * The packet data includes stuff such as the AAL5 trailer, if
993 * it wasn't cut off by the snapshot length.
994 * Decode the trailer, if present, and then chop it off.
996 length = tvb_length(tvb);
997 reported_length = tvb_reported_length(tvb);
998 if ((reported_length % 48) == 0) {
1000 * Reported length is a multiple of 48, so we can presumably
1001 * divide it by 48 to get the number of cells.
1003 proto_tree_add_text(atm_tree, tvb, 0, 0, "Cells: %u",
1004 reported_length/48);
1006 if (length >= reported_length) {
1008 * XXX - what if the packet is truncated? Can that happen?
1009 * What if you capture with Windows Sniffer on an ATM link
1010 * and tell it not to save the entire packet? What happens
1013 aal5_length = tvb_get_ntohs(tvb, length - 6);
1015 pad_length = length - aal5_length - 8;
1016 if (pad_length > 0) {
1017 proto_tree_add_text(atm_tree, tvb, aal5_length, pad_length,
1020 proto_tree_add_text(atm_tree, tvb, length - 8, 1, "AAL5 UU: 0x%02x",
1021 tvb_get_guint8(tvb, length - 8));
1022 proto_tree_add_text(atm_tree, tvb, length - 7, 1, "AAL5 CPI: 0x%02x",
1023 tvb_get_guint8(tvb, length - 7));
1024 proto_tree_add_text(atm_tree, tvb, length - 6, 2, "AAL5 len: %u",
1026 crc = tvb_get_ntohl(tvb, length - 4);
1027 calc_crc = update_crc(0xFFFFFFFF, tvb_get_ptr(tvb, 0, length),
1029 proto_tree_add_text(atm_tree, tvb, length - 4, 4,
1030 "AAL5 CRC (%s): 0x%08X",
1031 (calc_crc == 0xC704DD7B) ? "correct" : "incorrect", crc);
1033 next_tvb = tvb_new_subset(tvb, 0, aal5_length, aal5_length);
1037 switch (pinfo->pseudo_header->atm.aal) {
1039 case AAL_SIGNALLING:
1040 call_dissector(sscop_handle, next_tvb, pinfo, tree);
1044 switch (pinfo->pseudo_header->atm.type) {
1047 call_dissector(llc_handle, next_tvb, pinfo, tree);
1051 call_dissector(lane_handle, next_tvb, pinfo, tree);
1055 call_dissector(ilmi_handle, next_tvb, pinfo, tree);
1060 /* Dump it as raw data. */
1061 call_dissector(data_handle, next_tvb, pinfo, tree);
1070 * Charles Michael Heard's HEC code, from
1072 * http://cell-relay.indiana.edu/cell-relay/publications/software/CRC/32bitCRC.tutorial.html
1074 * with the syndrome and error position tables initialized with values
1075 * computed by his "gen_syndrome_table()" and "gen_err_posn_table()" routines,
1076 * rather than by calling those routines at run time, and with various data
1077 * type cleanups and changes not to correct the header if a correctible
1078 * error was detected.
1080 #define COSET_LEADER 0x055 /* x^6 + x^4 + x^2 + 1 */
1082 static const guint8 syndrome_table[256] = {
1083 0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15,
1084 0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d,
1085 0x70, 0x77, 0x7e, 0x79, 0x6c, 0x6b, 0x62, 0x65,
1086 0x48, 0x4f, 0x46, 0x41, 0x54, 0x53, 0x5a, 0x5d,
1087 0xe0, 0xe7, 0xee, 0xe9, 0xfc, 0xfb, 0xf2, 0xf5,
1088 0xd8, 0xdf, 0xd6, 0xd1, 0xc4, 0xc3, 0xca, 0xcd,
1089 0x90, 0x97, 0x9e, 0x99, 0x8c, 0x8b, 0x82, 0x85,
1090 0xa8, 0xaf, 0xa6, 0xa1, 0xb4, 0xb3, 0xba, 0xbd,
1091 0xc7, 0xc0, 0xc9, 0xce, 0xdb, 0xdc, 0xd5, 0xd2,
1092 0xff, 0xf8, 0xf1, 0xf6, 0xe3, 0xe4, 0xed, 0xea,
1093 0xb7, 0xb0, 0xb9, 0xbe, 0xab, 0xac, 0xa5, 0xa2,
1094 0x8f, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9d, 0x9a,
1095 0x27, 0x20, 0x29, 0x2e, 0x3b, 0x3c, 0x35, 0x32,
1096 0x1f, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0d, 0x0a,
1097 0x57, 0x50, 0x59, 0x5e, 0x4b, 0x4c, 0x45, 0x42,
1098 0x6f, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7d, 0x7a,
1099 0x89, 0x8e, 0x87, 0x80, 0x95, 0x92, 0x9b, 0x9c,
1100 0xb1, 0xb6, 0xbf, 0xb8, 0xad, 0xaa, 0xa3, 0xa4,
1101 0xf9, 0xfe, 0xf7, 0xf0, 0xe5, 0xe2, 0xeb, 0xec,
1102 0xc1, 0xc6, 0xcf, 0xc8, 0xdd, 0xda, 0xd3, 0xd4,
1103 0x69, 0x6e, 0x67, 0x60, 0x75, 0x72, 0x7b, 0x7c,
1104 0x51, 0x56, 0x5f, 0x58, 0x4d, 0x4a, 0x43, 0x44,
1105 0x19, 0x1e, 0x17, 0x10, 0x05, 0x02, 0x0b, 0x0c,
1106 0x21, 0x26, 0x2f, 0x28, 0x3d, 0x3a, 0x33, 0x34,
1107 0x4e, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5c, 0x5b,
1108 0x76, 0x71, 0x78, 0x7f, 0x6a, 0x6d, 0x64, 0x63,
1109 0x3e, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2c, 0x2b,
1110 0x06, 0x01, 0x08, 0x0f, 0x1a, 0x1d, 0x14, 0x13,
1111 0xae, 0xa9, 0xa0, 0xa7, 0xb2, 0xb5, 0xbc, 0xbb,
1112 0x96, 0x91, 0x98, 0x9f, 0x8a, 0x8d, 0x84, 0x83,
1113 0xde, 0xd9, 0xd0, 0xd7, 0xc2, 0xc5, 0xcc, 0xcb,
1114 0xe6, 0xe1, 0xe8, 0xef, 0xfa, 0xfd, 0xf4, 0xf3,
1117 #define NO_ERROR_DETECTED -128
1118 #define UNCORRECTIBLE_ERROR 128
1120 static const int err_posn_table[256] = {
1121 NO_ERROR_DETECTED, 37,
1122 36, UNCORRECTIBLE_ERROR,
1123 35, UNCORRECTIBLE_ERROR,
1124 UNCORRECTIBLE_ERROR, 29,
1125 34, UNCORRECTIBLE_ERROR,
1126 UNCORRECTIBLE_ERROR, 6,
1127 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1128 28, UNCORRECTIBLE_ERROR,
1129 33, UNCORRECTIBLE_ERROR,
1130 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1131 UNCORRECTIBLE_ERROR, 21,
1132 5, UNCORRECTIBLE_ERROR,
1133 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1134 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1135 27, UNCORRECTIBLE_ERROR,
1136 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1137 32, UNCORRECTIBLE_ERROR,
1138 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1139 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1140 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1141 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1142 20, UNCORRECTIBLE_ERROR,
1143 4, UNCORRECTIBLE_ERROR,
1144 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1145 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1146 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1147 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1148 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1149 26, UNCORRECTIBLE_ERROR,
1150 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1151 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1152 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1156 * Return an indication of whether there was an error in the cell header
1157 * and, if so, where the error was, if it was correctable.
1160 get_header_err(const guint8 *cell_header)
1162 register guint8 syndrome;
1163 register int i, err_posn;
1166 for (i = 0; i < 4; i++)
1167 syndrome = syndrome_table[syndrome ^ cell_header[i]];
1168 syndrome ^= cell_header[4] ^ COSET_LEADER;
1170 err_posn = err_posn_table [syndrome];
1173 return NO_ERROR_DETECTED;
1174 else if (err_posn < 40)
1177 return UNCORRECTIBLE_ERROR;
1180 static const value_string pt_vals[] = {
1181 { 0, "User data cell, congestion not experienced, SDU-type = 0" },
1182 { 1, "User data cell, congestion not experienced, SDU-type = 1" },
1183 { 2, "User data cell, congestion experienced, SDU-type = 0" },
1184 { 3, "User data cell, congestion experienced, SDU-type = 1" },
1185 { 4, "Segment OAM F5 flow related cell" },
1186 { 5, "End-to-end OAM F5 flow related cell" },
1191 * Charles Michael Heard's CRC-10 code, from
1193 * http://cell-relay.indiana.edu/cell-relay/publications/software/CRC/crc10.html
1195 * with the CRC table initialized with values computed by
1196 * his "gen_byte_crc10_table()" routine, rather than by calling that
1197 * routine at run time, and with various data type cleanups.
1199 static const guint16 byte_crc10_table[256] = {
1200 0x0000, 0x0233, 0x0255, 0x0066, 0x0299, 0x00aa, 0x00cc, 0x02ff,
1201 0x0301, 0x0132, 0x0154, 0x0367, 0x0198, 0x03ab, 0x03cd, 0x01fe,
1202 0x0031, 0x0202, 0x0264, 0x0057, 0x02a8, 0x009b, 0x00fd, 0x02ce,
1203 0x0330, 0x0103, 0x0165, 0x0356, 0x01a9, 0x039a, 0x03fc, 0x01cf,
1204 0x0062, 0x0251, 0x0237, 0x0004, 0x02fb, 0x00c8, 0x00ae, 0x029d,
1205 0x0363, 0x0150, 0x0136, 0x0305, 0x01fa, 0x03c9, 0x03af, 0x019c,
1206 0x0053, 0x0260, 0x0206, 0x0035, 0x02ca, 0x00f9, 0x009f, 0x02ac,
1207 0x0352, 0x0161, 0x0107, 0x0334, 0x01cb, 0x03f8, 0x039e, 0x01ad,
1208 0x00c4, 0x02f7, 0x0291, 0x00a2, 0x025d, 0x006e, 0x0008, 0x023b,
1209 0x03c5, 0x01f6, 0x0190, 0x03a3, 0x015c, 0x036f, 0x0309, 0x013a,
1210 0x00f5, 0x02c6, 0x02a0, 0x0093, 0x026c, 0x005f, 0x0039, 0x020a,
1211 0x03f4, 0x01c7, 0x01a1, 0x0392, 0x016d, 0x035e, 0x0338, 0x010b,
1212 0x00a6, 0x0295, 0x02f3, 0x00c0, 0x023f, 0x000c, 0x006a, 0x0259,
1213 0x03a7, 0x0194, 0x01f2, 0x03c1, 0x013e, 0x030d, 0x036b, 0x0158,
1214 0x0097, 0x02a4, 0x02c2, 0x00f1, 0x020e, 0x003d, 0x005b, 0x0268,
1215 0x0396, 0x01a5, 0x01c3, 0x03f0, 0x010f, 0x033c, 0x035a, 0x0169,
1216 0x0188, 0x03bb, 0x03dd, 0x01ee, 0x0311, 0x0122, 0x0144, 0x0377,
1217 0x0289, 0x00ba, 0x00dc, 0x02ef, 0x0010, 0x0223, 0x0245, 0x0076,
1218 0x01b9, 0x038a, 0x03ec, 0x01df, 0x0320, 0x0113, 0x0175, 0x0346,
1219 0x02b8, 0x008b, 0x00ed, 0x02de, 0x0021, 0x0212, 0x0274, 0x0047,
1220 0x01ea, 0x03d9, 0x03bf, 0x018c, 0x0373, 0x0140, 0x0126, 0x0315,
1221 0x02eb, 0x00d8, 0x00be, 0x028d, 0x0072, 0x0241, 0x0227, 0x0014,
1222 0x01db, 0x03e8, 0x038e, 0x01bd, 0x0342, 0x0171, 0x0117, 0x0324,
1223 0x02da, 0x00e9, 0x008f, 0x02bc, 0x0043, 0x0270, 0x0216, 0x0025,
1224 0x014c, 0x037f, 0x0319, 0x012a, 0x03d5, 0x01e6, 0x0180, 0x03b3,
1225 0x024d, 0x007e, 0x0018, 0x022b, 0x00d4, 0x02e7, 0x0281, 0x00b2,
1226 0x017d, 0x034e, 0x0328, 0x011b, 0x03e4, 0x01d7, 0x01b1, 0x0382,
1227 0x027c, 0x004f, 0x0029, 0x021a, 0x00e5, 0x02d6, 0x02b0, 0x0083,
1228 0x012e, 0x031d, 0x037b, 0x0148, 0x03b7, 0x0184, 0x01e2, 0x03d1,
1229 0x022f, 0x001c, 0x007a, 0x0249, 0x00b6, 0x0285, 0x02e3, 0x00d0,
1230 0x011f, 0x032c, 0x034a, 0x0179, 0x0386, 0x01b5, 0x01d3, 0x03e0,
1231 0x021e, 0x002d, 0x004b, 0x0278, 0x0087, 0x02b4, 0x02d2, 0x00e1,
1234 /* update the data block's CRC-10 remainder one byte at a time */
1236 update_crc10_by_bytes(guint16 crc10_accum, const guint8 *data_blk_ptr,
1241 for (i = 0; i < data_blk_size; i++) {
1242 crc10_accum = ((crc10_accum << 8) & 0x3ff)
1243 ^ byte_crc10_table[( crc10_accum >> 2) & 0xff]
1249 static const value_string st_vals[] = {
1257 #define OAM_TYPE_FM 1 /* Fault Management */
1258 #define OAM_TYPE_PM 2 /* Performance Management */
1259 #define OAM_TYPE_AD 8 /* Activation/Deactivation */
1261 static const value_string oam_type_vals[] = {
1262 { OAM_TYPE_FM, "Fault Management" },
1263 { OAM_TYPE_PM, "Performance Management" },
1264 { OAM_TYPE_AD, "Activation/Deactivation" },
1268 static const value_string ft_fm_vals[] = {
1269 { 0, "Alarm Indication Signal" },
1270 { 1, "Far End Receive Failure" },
1271 { 8, "OAM Cell Loopback" },
1272 { 4, "Continuity Check" },
1276 static const value_string ft_pm_vals[] = {
1277 { 0, "Forward Monitoring" },
1278 { 1, "Backward Reporting" },
1279 { 2, "Monitoring and Reporting" },
1283 static const value_string ft_ad_vals[] = {
1284 { 0, "Performance Monitoring" },
1285 { 1, "Continuity Check" },
1290 dissect_atm_cell(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1291 proto_tree *atm_tree)
1294 proto_tree *aal_tree;
1300 guint16 aal3_4_hdr, aal3_4_trlr;
1306 octet = tvb_get_guint8(tvb, 0);
1307 proto_tree_add_text(atm_tree, tvb, 0, 1, "GFC: 0x%x", octet >> 4);
1308 vpi = (octet & 0xF0) << 4;
1309 octet = tvb_get_guint8(tvb, 1);
1311 proto_tree_add_uint(atm_tree, hf_atm_vpi, tvb, 0, 2, vpi);
1312 vci = (octet & 0x0F) << 12;
1313 octet = tvb_get_guint8(tvb, 2);
1315 octet = tvb_get_guint8(tvb, 3);
1317 proto_tree_add_uint(atm_tree, hf_atm_vci, tvb, 1, 3, vci);
1318 proto_tree_add_text(atm_tree, tvb, 3, 1, "Payload Type: %s",
1319 val_to_str((octet >> 1) & 0x7, pt_vals, "Unknown (%u)"));
1320 proto_tree_add_text(atm_tree, tvb, 3, 1, "Cell Loss Priority: %s",
1321 (octet & 0x01) ? "Low priority" : "High priority");
1322 ti = proto_tree_add_text(atm_tree, tvb, 4, 1, "Header Error Check: 0x%02x",
1323 tvb_get_guint8(tvb, 4));
1324 err = get_header_err(tvb_get_ptr(tvb, 0, 5));
1325 if (err == NO_ERROR_DETECTED)
1326 proto_item_append_text(ti, " (correct)");
1327 else if (err == UNCORRECTIBLE_ERROR)
1328 proto_item_append_text(ti, " (uncorrectable error)");
1330 proto_item_append_text(ti, " (error in bit %d)", err);
1333 switch (pinfo->pseudo_header->atm.aal) {
1336 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1337 col_set_str(pinfo->cinfo, COL_PROTOCOL, "AAL1");
1338 ti = proto_tree_add_item(tree, proto_aal1, tvb, offset, -1, FALSE);
1339 aal_tree = proto_item_add_subtree(ti, ett_aal1);
1340 octet = tvb_get_guint8(tvb, offset);
1341 proto_tree_add_text(aal_tree, tvb, offset, 1, "CSI: %u", octet >> 7);
1342 proto_tree_add_text(aal_tree, tvb, offset, 1, "Sequence Count: %u",
1343 (octet >> 4) & 0x7);
1344 if (check_col(pinfo->cinfo, COL_INFO)) {
1345 col_add_fstr(pinfo->cinfo, COL_INFO, "Sequence count = %u",
1346 (octet >> 4) & 0x7);
1348 proto_tree_add_text(aal_tree, tvb, offset, 1, "CRC: 0x%x",
1349 (octet >> 1) & 0x7);
1350 proto_tree_add_text(aal_tree, tvb, offset, 1, "Parity: %u",
1354 proto_tree_add_text(aal_tree, tvb, offset, 47, "Payload");
1359 * XXX - or should this be the CS PDU?
1361 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1362 col_set_str(pinfo->cinfo, COL_PROTOCOL, "AAL3/4");
1363 ti = proto_tree_add_item(tree, proto_aal3_4, tvb, offset, -1, FALSE);
1364 aal_tree = proto_item_add_subtree(ti, ett_aal3_4);
1365 aal3_4_hdr = tvb_get_ntohs(tvb, offset);
1366 if (check_col(pinfo->cinfo, COL_INFO)) {
1367 col_add_fstr(pinfo->cinfo, COL_INFO, "%s, sequence number = %u",
1368 val_to_str(aal3_4_hdr >> 14, st_vals, "Unknown (%u)"),
1369 (aal3_4_hdr >> 10) & 0xF);
1371 proto_tree_add_text(aal_tree, tvb, offset, 2, "Segment Type: %s",
1372 val_to_str(aal3_4_hdr >> 14, st_vals, "Unknown (%u)"));
1373 proto_tree_add_text(aal_tree, tvb, offset, 2, "Sequence Number: %u",
1374 (aal3_4_hdr >> 10) & 0xF);
1375 proto_tree_add_text(aal_tree, tvb, offset, 2, "Multiplex ID: %u",
1376 aal3_4_hdr & 0x3FF);
1379 proto_tree_add_text(aal_tree, tvb, offset, 44, "Information");
1382 aal3_4_trlr = tvb_get_ntohs(tvb, offset);
1383 proto_tree_add_text(aal_tree, tvb, offset, 2, "Length Indicator: %u",
1384 (aal3_4_trlr >> 10) & 0x3F);
1385 length = tvb_length_remaining(tvb, 5);
1386 crc10 = update_crc10_by_bytes(0, tvb_get_ptr(tvb, 5, length),
1388 proto_tree_add_text(aal_tree, tvb, offset, 2, "CRC: 0x%03x (%s)",
1389 aal3_4_trlr & 0x3FF,
1390 (crc10 == 0) ? "correct" : "incorrect");
1394 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1395 col_set_str(pinfo->cinfo, COL_PROTOCOL, "OAM AAL");
1396 ti = proto_tree_add_item(tree, proto_oamaal, tvb, offset, -1, FALSE);
1397 aal_tree = proto_item_add_subtree(ti, ett_oamaal);
1398 octet = tvb_get_guint8(tvb, offset);
1399 proto_tree_add_text(aal_tree, tvb, offset, 2, "OAM Type: %s",
1400 val_to_str(octet >> 4, oam_type_vals, "Unknown (%u)"));
1401 switch (octet >> 4) {
1404 proto_tree_add_text(aal_tree, tvb, offset, 2, "Function Type: %s",
1405 val_to_str(octet & 0x0F, ft_fm_vals, "Unknown (%u)"));
1409 proto_tree_add_text(aal_tree, tvb, offset, 2, "Function Type: %s",
1410 val_to_str(octet & 0x0F, ft_pm_vals, "Unknown (%u)"));
1414 proto_tree_add_text(aal_tree, tvb, offset, 2, "Function Type: %s",
1415 val_to_str(octet & 0x0F, ft_ad_vals, "Unknown (%u)"));
1419 proto_tree_add_text(aal_tree, tvb, offset, 2, "Function Type: %u",
1425 proto_tree_add_text(aal_tree, tvb, offset, 45, "Function-specific information");
1428 length = tvb_length_remaining(tvb, 5);
1429 crc10 = update_crc10_by_bytes(0, tvb_get_ptr(tvb, 5, length),
1431 oam_crc = tvb_get_ntohs(tvb, offset);
1432 proto_tree_add_text(aal_tree, tvb, offset, 2, "CRC-10: 0x%03x (%s)",
1434 (crc10 == 0) ? "correct" : "incorrect");
1438 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
1439 call_dissector(data_handle, next_tvb, pinfo, tree);
1445 dissect_atm_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1448 proto_tree *atm_tree = NULL;
1449 proto_item *ti = NULL;
1451 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1452 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATM");
1454 switch (pinfo->pseudo_header->atm.channel) {
1457 /* Traffic from DTE to DCE. */
1458 if (check_col(pinfo->cinfo, COL_RES_DL_DST))
1459 col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DCE");
1460 if (check_col(pinfo->cinfo, COL_RES_DL_SRC))
1461 col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DTE");
1465 /* Traffic from DCE to DTE. */
1466 if (check_col(pinfo->cinfo, COL_RES_DL_DST))
1467 col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DTE");
1468 if (check_col(pinfo->cinfo, COL_RES_DL_SRC))
1469 col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DCE");
1473 if (check_col(pinfo->cinfo, COL_INFO)) {
1474 if (pinfo->pseudo_header->atm.aal == AAL_5) {
1475 col_add_fstr(pinfo->cinfo, COL_INFO, "AAL5 %s",
1476 val_to_str(pinfo->pseudo_header->atm.type, aal5_hltype_vals,
1477 "Unknown traffic type (%u)"));
1479 col_add_str(pinfo->cinfo, COL_INFO,
1480 val_to_str(pinfo->pseudo_header->atm.aal, aal_vals,
1481 "Unknown AAL (%u)"));
1486 ti = proto_tree_add_protocol_format(tree, proto_atm, tvb, 0, 0, "ATM");
1487 atm_tree = proto_item_add_subtree(ti, ett_atm);
1489 switch (pinfo->pseudo_header->atm.channel) {
1492 /* Traffic from DTE to DCE. */
1493 proto_tree_add_text(atm_tree, tvb, 0, 0, "Channel: DTE->DCE");
1497 /* Traffic from DCE to DTE. */
1498 proto_tree_add_text(atm_tree, tvb, 0, 0, "Channel: DCE->DTE");
1502 /* Sniffers shouldn't provide anything other than 0 or 1. */
1503 proto_tree_add_text(atm_tree, tvb, 0, 0, "Channel: %u",
1504 pinfo->pseudo_header->atm.channel);
1508 proto_tree_add_uint_format(atm_tree, hf_atm_aal, tvb, 0, 0,
1509 pinfo->pseudo_header->atm.aal,
1511 val_to_str(pinfo->pseudo_header->atm.aal, aal_vals,
1512 "Unknown AAL (%u)"));
1514 if (pinfo->pseudo_header->atm.flags & ATM_IS_CELL) {
1515 /* This is a single cell, with the cell header at the beginning. */
1516 proto_item_set_len(ti, 5);
1517 dissect_atm_cell(tvb, pinfo, tree, atm_tree);
1519 /* This is a reassembled PDU. */
1520 dissect_reassembled_pdu(tvb, pinfo, tree, atm_tree, truncated);
1525 dissect_atm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1527 dissect_atm_common(tvb, pinfo, tree, TRUE);
1531 dissect_atm_untruncated(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1533 dissect_atm_common(tvb, pinfo, tree, FALSE);
1537 proto_register_atm(void)
1539 static hf_register_info hf[] = {
1541 { "AAL", "atm.aal", FT_UINT8, BASE_DEC, VALS(aal_vals), 0x0,
1545 { "VPI", "atm.vpi", FT_UINT8, BASE_DEC, NULL, 0x0,
1549 { "VCI", "atm.vci", FT_UINT16, BASE_DEC, NULL, 0x0,
1552 static gint *ett[] = {
1559 &ett_atm_lane_lc_lan_dest,
1560 &ett_atm_lane_lc_lan_dest_rd,
1561 &ett_atm_lane_lc_flags,
1562 &ett_atm_lane_lc_tlv,
1564 proto_atm = proto_register_protocol("ATM", "ATM", "atm");
1565 proto_aal1 = proto_register_protocol("ATM AAL1", "AAL1", "aal1");
1566 proto_aal3_4 = proto_register_protocol("ATM AAL3/4", "AAL3_4", "aal3_4");
1567 proto_oamaal = proto_register_protocol("ATM OAM AAL", "OAM AAL", "oamaal");
1568 proto_register_field_array(proto_atm, hf, array_length(hf));
1569 proto_register_subtree_array(ett, array_length(ett));
1571 proto_ilmi = proto_register_protocol("ILMI", "ILMI", "ilmi");
1573 register_dissector("ilmi", dissect_ilmi, proto_ilmi);
1575 proto_atm_lane = proto_register_protocol("ATM LAN Emulation",
1576 "ATM LANE", "lane");
1578 register_dissector("lane", dissect_lane, proto_atm_lane);
1582 proto_reg_handoff_atm(void)
1584 dissector_handle_t atm_handle, atm_untruncated_handle;
1587 * Get handles for the Ethernet, Token Ring, LLC, SSCOP, LANE,
1588 * and ILMI dissectors.
1590 eth_handle = find_dissector("eth");
1591 tr_handle = find_dissector("tr");
1592 llc_handle = find_dissector("llc");
1593 sscop_handle = find_dissector("sscop");
1594 lane_handle = find_dissector("lane");
1595 ilmi_handle = find_dissector("ilmi");
1596 data_handle = find_dissector("data");
1598 atm_handle = create_dissector_handle(dissect_atm, proto_atm);
1599 dissector_add("wtap_encap", WTAP_ENCAP_ATM_PDUS, atm_handle);
1601 atm_untruncated_handle = create_dissector_handle(dissect_atm_untruncated,
1603 dissector_add("wtap_encap", WTAP_ENCAP_ATM_PDUS_UNTRUNCATED,
1604 atm_untruncated_handle);