2 * Routines for ATM packet disassembly
4 * $Id: packet-atm.c,v 1.61 2003/01/11 06:17:22 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 traffic type for AAL5 traffic, and the VPI and VCI,
929 * from the pseudo-header.
931 if (pinfo->pseudo_header->atm.aal == AAL_5) {
932 proto_tree_add_text(atm_tree, tvb, 0, 0, "Traffic type: %s",
933 val_to_str(pinfo->pseudo_header->atm.type, aal5_hltype_vals,
934 "Unknown AAL5 traffic type (%u)"));
935 switch (pinfo->pseudo_header->atm.type) {
938 proto_tree_add_text(atm_tree, tvb, 0, 0, "VC multiplexed traffic type: %s",
939 val_to_str(pinfo->pseudo_header->atm.subtype,
940 vcmx_type_vals, "Unknown VCMX traffic type (%u)"));
944 proto_tree_add_text(atm_tree, tvb, 0, 0, "LANE traffic type: %s",
945 val_to_str(pinfo->pseudo_header->atm.subtype,
946 lane_type_vals, "Unknown LANE traffic type (%u)"));
950 proto_tree_add_text(atm_tree, tvb, 0, 0, "Ipsilon traffic type: %s",
951 val_to_str(pinfo->pseudo_header->atm.subtype,
952 ipsilon_type_vals, "Unknown Ipsilon traffic type (%u)"));
956 proto_tree_add_uint(atm_tree, hf_atm_vpi, tvb, 0, 0,
957 pinfo->pseudo_header->atm.vpi);
958 proto_tree_add_uint(atm_tree, hf_atm_vci, tvb, 0, 0,
959 pinfo->pseudo_header->atm.vci);
964 * The packet data does not include stuff such as the AAL5
967 if (pinfo->pseudo_header->atm.cells != 0) {
969 * If the cell count is 0, assume it means we don't know how
972 * XXX - also assume it means we don't know what was in the AAL5
973 * trailer. We may, however, find some capture program that can
974 * give us the AAL5 trailer information but not the cell count,
975 * in which case we need some other way of indicating whether we
976 * have the AAL5 trailer information.
979 proto_tree_add_text(atm_tree, tvb, 0, 0, "Cells: %u",
980 pinfo->pseudo_header->atm.cells);
981 proto_tree_add_text(atm_tree, tvb, 0, 0, "AAL5 UU: 0x%02x",
982 pinfo->pseudo_header->atm.aal5t_u2u >> 8);
983 proto_tree_add_text(atm_tree, tvb, 0, 0, "AAL5 CPI: 0x%02x",
984 pinfo->pseudo_header->atm.aal5t_u2u & 0xFF);
985 proto_tree_add_text(atm_tree, tvb, 0, 0, "AAL5 len: %u",
986 pinfo->pseudo_header->atm.aal5t_len);
987 proto_tree_add_text(atm_tree, tvb, 0, 0, "AAL5 CRC: 0x%08X",
988 pinfo->pseudo_header->atm.aal5t_chksum);
993 * The packet data includes stuff such as the AAL5 trailer, if
994 * it wasn't cut off by the snapshot length.
995 * Decode the trailer, if present, and then chop it off.
997 length = tvb_length(tvb);
998 reported_length = tvb_reported_length(tvb);
999 if ((reported_length % 48) == 0) {
1001 * Reported length is a multiple of 48, so we can presumably
1002 * divide it by 48 to get the number of cells.
1004 proto_tree_add_text(atm_tree, tvb, 0, 0, "Cells: %u",
1005 reported_length/48);
1007 if (length >= reported_length) {
1009 * XXX - what if the packet is truncated? Can that happen?
1010 * What if you capture with Windows Sniffer on an ATM link
1011 * and tell it not to save the entire packet? What happens
1014 aal5_length = tvb_get_ntohs(tvb, length - 6);
1016 pad_length = length - aal5_length - 8;
1017 if (pad_length > 0) {
1018 proto_tree_add_text(atm_tree, tvb, aal5_length, pad_length,
1021 proto_tree_add_text(atm_tree, tvb, length - 8, 1, "AAL5 UU: 0x%02x",
1022 tvb_get_guint8(tvb, length - 8));
1023 proto_tree_add_text(atm_tree, tvb, length - 7, 1, "AAL5 CPI: 0x%02x",
1024 tvb_get_guint8(tvb, length - 7));
1025 proto_tree_add_text(atm_tree, tvb, length - 6, 2, "AAL5 len: %u",
1027 crc = tvb_get_ntohl(tvb, length - 4);
1028 calc_crc = update_crc(0xFFFFFFFF, tvb_get_ptr(tvb, 0, length),
1030 proto_tree_add_text(atm_tree, tvb, length - 4, 4,
1031 "AAL5 CRC: 0x%08X (%s)", crc,
1032 (calc_crc == 0xC704DD7B) ? "correct" : "incorrect");
1034 next_tvb = tvb_new_subset(tvb, 0, aal5_length, aal5_length);
1038 switch (pinfo->pseudo_header->atm.aal) {
1040 case AAL_SIGNALLING:
1041 call_dissector(sscop_handle, next_tvb, pinfo, tree);
1045 switch (pinfo->pseudo_header->atm.type) {
1048 call_dissector(llc_handle, next_tvb, pinfo, tree);
1052 call_dissector(lane_handle, next_tvb, pinfo, tree);
1056 call_dissector(ilmi_handle, next_tvb, pinfo, tree);
1061 /* Dump it as raw data. */
1062 call_dissector(data_handle, next_tvb, pinfo, tree);
1070 /* Dump it as raw data. */
1071 call_dissector(data_handle, next_tvb, pinfo, tree);
1078 * Charles Michael Heard's HEC code, from
1080 * http://cell-relay.indiana.edu/cell-relay/publications/software/CRC/32bitCRC.tutorial.html
1082 * with the syndrome and error position tables initialized with values
1083 * computed by his "gen_syndrome_table()" and "gen_err_posn_table()" routines,
1084 * rather than by calling those routines at run time, and with various data
1085 * type cleanups and changes not to correct the header if a correctible
1086 * error was detected.
1088 #define COSET_LEADER 0x055 /* x^6 + x^4 + x^2 + 1 */
1090 static const guint8 syndrome_table[256] = {
1091 0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15,
1092 0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d,
1093 0x70, 0x77, 0x7e, 0x79, 0x6c, 0x6b, 0x62, 0x65,
1094 0x48, 0x4f, 0x46, 0x41, 0x54, 0x53, 0x5a, 0x5d,
1095 0xe0, 0xe7, 0xee, 0xe9, 0xfc, 0xfb, 0xf2, 0xf5,
1096 0xd8, 0xdf, 0xd6, 0xd1, 0xc4, 0xc3, 0xca, 0xcd,
1097 0x90, 0x97, 0x9e, 0x99, 0x8c, 0x8b, 0x82, 0x85,
1098 0xa8, 0xaf, 0xa6, 0xa1, 0xb4, 0xb3, 0xba, 0xbd,
1099 0xc7, 0xc0, 0xc9, 0xce, 0xdb, 0xdc, 0xd5, 0xd2,
1100 0xff, 0xf8, 0xf1, 0xf6, 0xe3, 0xe4, 0xed, 0xea,
1101 0xb7, 0xb0, 0xb9, 0xbe, 0xab, 0xac, 0xa5, 0xa2,
1102 0x8f, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9d, 0x9a,
1103 0x27, 0x20, 0x29, 0x2e, 0x3b, 0x3c, 0x35, 0x32,
1104 0x1f, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0d, 0x0a,
1105 0x57, 0x50, 0x59, 0x5e, 0x4b, 0x4c, 0x45, 0x42,
1106 0x6f, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7d, 0x7a,
1107 0x89, 0x8e, 0x87, 0x80, 0x95, 0x92, 0x9b, 0x9c,
1108 0xb1, 0xb6, 0xbf, 0xb8, 0xad, 0xaa, 0xa3, 0xa4,
1109 0xf9, 0xfe, 0xf7, 0xf0, 0xe5, 0xe2, 0xeb, 0xec,
1110 0xc1, 0xc6, 0xcf, 0xc8, 0xdd, 0xda, 0xd3, 0xd4,
1111 0x69, 0x6e, 0x67, 0x60, 0x75, 0x72, 0x7b, 0x7c,
1112 0x51, 0x56, 0x5f, 0x58, 0x4d, 0x4a, 0x43, 0x44,
1113 0x19, 0x1e, 0x17, 0x10, 0x05, 0x02, 0x0b, 0x0c,
1114 0x21, 0x26, 0x2f, 0x28, 0x3d, 0x3a, 0x33, 0x34,
1115 0x4e, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5c, 0x5b,
1116 0x76, 0x71, 0x78, 0x7f, 0x6a, 0x6d, 0x64, 0x63,
1117 0x3e, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2c, 0x2b,
1118 0x06, 0x01, 0x08, 0x0f, 0x1a, 0x1d, 0x14, 0x13,
1119 0xae, 0xa9, 0xa0, 0xa7, 0xb2, 0xb5, 0xbc, 0xbb,
1120 0x96, 0x91, 0x98, 0x9f, 0x8a, 0x8d, 0x84, 0x83,
1121 0xde, 0xd9, 0xd0, 0xd7, 0xc2, 0xc5, 0xcc, 0xcb,
1122 0xe6, 0xe1, 0xe8, 0xef, 0xfa, 0xfd, 0xf4, 0xf3,
1125 #define NO_ERROR_DETECTED -128
1126 #define UNCORRECTIBLE_ERROR 128
1128 static const int err_posn_table[256] = {
1129 NO_ERROR_DETECTED, 37,
1130 36, UNCORRECTIBLE_ERROR,
1131 35, UNCORRECTIBLE_ERROR,
1132 UNCORRECTIBLE_ERROR, 29,
1133 34, UNCORRECTIBLE_ERROR,
1134 UNCORRECTIBLE_ERROR, 6,
1135 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1136 28, UNCORRECTIBLE_ERROR,
1137 33, UNCORRECTIBLE_ERROR,
1138 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1139 UNCORRECTIBLE_ERROR, 21,
1140 5, UNCORRECTIBLE_ERROR,
1141 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1142 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1143 27, UNCORRECTIBLE_ERROR,
1144 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1145 32, UNCORRECTIBLE_ERROR,
1146 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1147 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1148 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1149 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1150 20, UNCORRECTIBLE_ERROR,
1151 4, UNCORRECTIBLE_ERROR,
1152 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1153 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1154 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1155 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1156 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1157 26, UNCORRECTIBLE_ERROR,
1158 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1159 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1160 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1164 * Return an indication of whether there was an error in the cell header
1165 * and, if so, where the error was, if it was correctable.
1168 get_header_err(const guint8 *cell_header)
1170 register guint8 syndrome;
1171 register int i, err_posn;
1174 for (i = 0; i < 4; i++)
1175 syndrome = syndrome_table[syndrome ^ cell_header[i]];
1176 syndrome ^= cell_header[4] ^ COSET_LEADER;
1178 err_posn = err_posn_table [syndrome];
1181 return NO_ERROR_DETECTED;
1182 else if (err_posn < 40)
1185 return UNCORRECTIBLE_ERROR;
1188 static const value_string pt_vals[] = {
1189 { 0, "User data cell, congestion not experienced, SDU-type = 0" },
1190 { 1, "User data cell, congestion not experienced, SDU-type = 1" },
1191 { 2, "User data cell, congestion experienced, SDU-type = 0" },
1192 { 3, "User data cell, congestion experienced, SDU-type = 1" },
1193 { 4, "Segment OAM F5 flow related cell" },
1194 { 5, "End-to-end OAM F5 flow related cell" },
1199 * Charles Michael Heard's CRC-10 code, from
1201 * http://cell-relay.indiana.edu/cell-relay/publications/software/CRC/crc10.html
1203 * with the CRC table initialized with values computed by
1204 * his "gen_byte_crc10_table()" routine, rather than by calling that
1205 * routine at run time, and with various data type cleanups.
1207 static const guint16 byte_crc10_table[256] = {
1208 0x0000, 0x0233, 0x0255, 0x0066, 0x0299, 0x00aa, 0x00cc, 0x02ff,
1209 0x0301, 0x0132, 0x0154, 0x0367, 0x0198, 0x03ab, 0x03cd, 0x01fe,
1210 0x0031, 0x0202, 0x0264, 0x0057, 0x02a8, 0x009b, 0x00fd, 0x02ce,
1211 0x0330, 0x0103, 0x0165, 0x0356, 0x01a9, 0x039a, 0x03fc, 0x01cf,
1212 0x0062, 0x0251, 0x0237, 0x0004, 0x02fb, 0x00c8, 0x00ae, 0x029d,
1213 0x0363, 0x0150, 0x0136, 0x0305, 0x01fa, 0x03c9, 0x03af, 0x019c,
1214 0x0053, 0x0260, 0x0206, 0x0035, 0x02ca, 0x00f9, 0x009f, 0x02ac,
1215 0x0352, 0x0161, 0x0107, 0x0334, 0x01cb, 0x03f8, 0x039e, 0x01ad,
1216 0x00c4, 0x02f7, 0x0291, 0x00a2, 0x025d, 0x006e, 0x0008, 0x023b,
1217 0x03c5, 0x01f6, 0x0190, 0x03a3, 0x015c, 0x036f, 0x0309, 0x013a,
1218 0x00f5, 0x02c6, 0x02a0, 0x0093, 0x026c, 0x005f, 0x0039, 0x020a,
1219 0x03f4, 0x01c7, 0x01a1, 0x0392, 0x016d, 0x035e, 0x0338, 0x010b,
1220 0x00a6, 0x0295, 0x02f3, 0x00c0, 0x023f, 0x000c, 0x006a, 0x0259,
1221 0x03a7, 0x0194, 0x01f2, 0x03c1, 0x013e, 0x030d, 0x036b, 0x0158,
1222 0x0097, 0x02a4, 0x02c2, 0x00f1, 0x020e, 0x003d, 0x005b, 0x0268,
1223 0x0396, 0x01a5, 0x01c3, 0x03f0, 0x010f, 0x033c, 0x035a, 0x0169,
1224 0x0188, 0x03bb, 0x03dd, 0x01ee, 0x0311, 0x0122, 0x0144, 0x0377,
1225 0x0289, 0x00ba, 0x00dc, 0x02ef, 0x0010, 0x0223, 0x0245, 0x0076,
1226 0x01b9, 0x038a, 0x03ec, 0x01df, 0x0320, 0x0113, 0x0175, 0x0346,
1227 0x02b8, 0x008b, 0x00ed, 0x02de, 0x0021, 0x0212, 0x0274, 0x0047,
1228 0x01ea, 0x03d9, 0x03bf, 0x018c, 0x0373, 0x0140, 0x0126, 0x0315,
1229 0x02eb, 0x00d8, 0x00be, 0x028d, 0x0072, 0x0241, 0x0227, 0x0014,
1230 0x01db, 0x03e8, 0x038e, 0x01bd, 0x0342, 0x0171, 0x0117, 0x0324,
1231 0x02da, 0x00e9, 0x008f, 0x02bc, 0x0043, 0x0270, 0x0216, 0x0025,
1232 0x014c, 0x037f, 0x0319, 0x012a, 0x03d5, 0x01e6, 0x0180, 0x03b3,
1233 0x024d, 0x007e, 0x0018, 0x022b, 0x00d4, 0x02e7, 0x0281, 0x00b2,
1234 0x017d, 0x034e, 0x0328, 0x011b, 0x03e4, 0x01d7, 0x01b1, 0x0382,
1235 0x027c, 0x004f, 0x0029, 0x021a, 0x00e5, 0x02d6, 0x02b0, 0x0083,
1236 0x012e, 0x031d, 0x037b, 0x0148, 0x03b7, 0x0184, 0x01e2, 0x03d1,
1237 0x022f, 0x001c, 0x007a, 0x0249, 0x00b6, 0x0285, 0x02e3, 0x00d0,
1238 0x011f, 0x032c, 0x034a, 0x0179, 0x0386, 0x01b5, 0x01d3, 0x03e0,
1239 0x021e, 0x002d, 0x004b, 0x0278, 0x0087, 0x02b4, 0x02d2, 0x00e1,
1242 /* update the data block's CRC-10 remainder one byte at a time */
1244 update_crc10_by_bytes(guint16 crc10_accum, const guint8 *data_blk_ptr,
1249 for (i = 0; i < data_blk_size; i++) {
1250 crc10_accum = ((crc10_accum << 8) & 0x3ff)
1251 ^ byte_crc10_table[( crc10_accum >> 2) & 0xff]
1257 static const value_string st_vals[] = {
1265 #define OAM_TYPE_FM 1 /* Fault Management */
1266 #define OAM_TYPE_PM 2 /* Performance Management */
1267 #define OAM_TYPE_AD 8 /* Activation/Deactivation */
1269 static const value_string oam_type_vals[] = {
1270 { OAM_TYPE_FM, "Fault Management" },
1271 { OAM_TYPE_PM, "Performance Management" },
1272 { OAM_TYPE_AD, "Activation/Deactivation" },
1276 static const value_string ft_fm_vals[] = {
1277 { 0, "Alarm Indication Signal" },
1278 { 1, "Far End Receive Failure" },
1279 { 8, "OAM Cell Loopback" },
1280 { 4, "Continuity Check" },
1284 static const value_string ft_pm_vals[] = {
1285 { 0, "Forward Monitoring" },
1286 { 1, "Backward Reporting" },
1287 { 2, "Monitoring and Reporting" },
1291 static const value_string ft_ad_vals[] = {
1292 { 0, "Performance Monitoring" },
1293 { 1, "Continuity Check" },
1298 dissect_atm_cell(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1299 proto_tree *atm_tree)
1302 proto_tree *aal_tree;
1308 guint16 aal3_4_hdr, aal3_4_trlr;
1314 octet = tvb_get_guint8(tvb, 0);
1315 proto_tree_add_text(atm_tree, tvb, 0, 1, "GFC: 0x%x", octet >> 4);
1316 vpi = (octet & 0xF0) << 4;
1317 octet = tvb_get_guint8(tvb, 1);
1319 proto_tree_add_uint(atm_tree, hf_atm_vpi, tvb, 0, 2, vpi);
1320 vci = (octet & 0x0F) << 12;
1321 octet = tvb_get_guint8(tvb, 2);
1323 octet = tvb_get_guint8(tvb, 3);
1325 proto_tree_add_uint(atm_tree, hf_atm_vci, tvb, 1, 3, vci);
1326 proto_tree_add_text(atm_tree, tvb, 3, 1, "Payload Type: %s",
1327 val_to_str((octet >> 1) & 0x7, pt_vals, "Unknown (%u)"));
1328 proto_tree_add_text(atm_tree, tvb, 3, 1, "Cell Loss Priority: %s",
1329 (octet & 0x01) ? "Low priority" : "High priority");
1330 ti = proto_tree_add_text(atm_tree, tvb, 4, 1, "Header Error Check: 0x%02x",
1331 tvb_get_guint8(tvb, 4));
1332 err = get_header_err(tvb_get_ptr(tvb, 0, 5));
1333 if (err == NO_ERROR_DETECTED)
1334 proto_item_append_text(ti, " (correct)");
1335 else if (err == UNCORRECTIBLE_ERROR)
1336 proto_item_append_text(ti, " (uncorrectable error)");
1338 proto_item_append_text(ti, " (error in bit %d)", err);
1341 switch (pinfo->pseudo_header->atm.aal) {
1344 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1345 col_set_str(pinfo->cinfo, COL_PROTOCOL, "AAL1");
1346 ti = proto_tree_add_item(tree, proto_aal1, tvb, offset, -1, FALSE);
1347 aal_tree = proto_item_add_subtree(ti, ett_aal1);
1348 octet = tvb_get_guint8(tvb, offset);
1349 proto_tree_add_text(aal_tree, tvb, offset, 1, "CSI: %u", octet >> 7);
1350 proto_tree_add_text(aal_tree, tvb, offset, 1, "Sequence Count: %u",
1351 (octet >> 4) & 0x7);
1352 if (check_col(pinfo->cinfo, COL_INFO)) {
1353 col_add_fstr(pinfo->cinfo, COL_INFO, "Sequence count = %u",
1354 (octet >> 4) & 0x7);
1356 proto_tree_add_text(aal_tree, tvb, offset, 1, "CRC: 0x%x",
1357 (octet >> 1) & 0x7);
1358 proto_tree_add_text(aal_tree, tvb, offset, 1, "Parity: %u",
1362 proto_tree_add_text(aal_tree, tvb, offset, 47, "Payload");
1367 * XXX - or should this be the CS PDU?
1369 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1370 col_set_str(pinfo->cinfo, COL_PROTOCOL, "AAL3/4");
1371 ti = proto_tree_add_item(tree, proto_aal3_4, tvb, offset, -1, FALSE);
1372 aal_tree = proto_item_add_subtree(ti, ett_aal3_4);
1373 aal3_4_hdr = tvb_get_ntohs(tvb, offset);
1374 if (check_col(pinfo->cinfo, COL_INFO)) {
1375 col_add_fstr(pinfo->cinfo, COL_INFO, "%s, sequence number = %u",
1376 val_to_str(aal3_4_hdr >> 14, st_vals, "Unknown (%u)"),
1377 (aal3_4_hdr >> 10) & 0xF);
1379 proto_tree_add_text(aal_tree, tvb, offset, 2, "Segment Type: %s",
1380 val_to_str(aal3_4_hdr >> 14, st_vals, "Unknown (%u)"));
1381 proto_tree_add_text(aal_tree, tvb, offset, 2, "Sequence Number: %u",
1382 (aal3_4_hdr >> 10) & 0xF);
1383 proto_tree_add_text(aal_tree, tvb, offset, 2, "Multiplex ID: %u",
1384 aal3_4_hdr & 0x3FF);
1387 proto_tree_add_text(aal_tree, tvb, offset, 44, "Information");
1390 aal3_4_trlr = tvb_get_ntohs(tvb, offset);
1391 proto_tree_add_text(aal_tree, tvb, offset, 2, "Length Indicator: %u",
1392 (aal3_4_trlr >> 10) & 0x3F);
1393 length = tvb_length_remaining(tvb, 5);
1394 crc10 = update_crc10_by_bytes(0, tvb_get_ptr(tvb, 5, length),
1396 proto_tree_add_text(aal_tree, tvb, offset, 2, "CRC: 0x%03x (%s)",
1397 aal3_4_trlr & 0x3FF,
1398 (crc10 == 0) ? "correct" : "incorrect");
1402 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1403 col_set_str(pinfo->cinfo, COL_PROTOCOL, "OAM AAL");
1404 ti = proto_tree_add_item(tree, proto_oamaal, tvb, offset, -1, FALSE);
1405 aal_tree = proto_item_add_subtree(ti, ett_oamaal);
1406 octet = tvb_get_guint8(tvb, offset);
1407 proto_tree_add_text(aal_tree, tvb, offset, 1, "OAM Type: %s",
1408 val_to_str(octet >> 4, oam_type_vals, "Unknown (%u)"));
1409 switch (octet >> 4) {
1412 proto_tree_add_text(aal_tree, tvb, offset, 1, "Function Type: %s",
1413 val_to_str(octet & 0x0F, ft_fm_vals, "Unknown (%u)"));
1417 proto_tree_add_text(aal_tree, tvb, offset, 1, "Function Type: %s",
1418 val_to_str(octet & 0x0F, ft_pm_vals, "Unknown (%u)"));
1422 proto_tree_add_text(aal_tree, tvb, offset, 1, "Function Type: %s",
1423 val_to_str(octet & 0x0F, ft_ad_vals, "Unknown (%u)"));
1427 proto_tree_add_text(aal_tree, tvb, offset, 1, "Function Type: %u",
1433 proto_tree_add_text(aal_tree, tvb, offset, 45, "Function-specific information");
1436 length = tvb_length_remaining(tvb, 5);
1437 crc10 = update_crc10_by_bytes(0, tvb_get_ptr(tvb, 5, length),
1439 oam_crc = tvb_get_ntohs(tvb, offset);
1440 proto_tree_add_text(aal_tree, tvb, offset, 2, "CRC-10: 0x%03x (%s)",
1442 (crc10 == 0) ? "correct" : "incorrect");
1446 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
1447 call_dissector(data_handle, next_tvb, pinfo, tree);
1453 dissect_atm_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1456 proto_tree *atm_tree = NULL;
1457 proto_item *ti = NULL;
1459 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1460 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATM");
1462 switch (pinfo->pseudo_header->atm.channel) {
1465 /* Traffic from DTE to DCE. */
1466 if (check_col(pinfo->cinfo, COL_RES_DL_DST))
1467 col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DCE");
1468 if (check_col(pinfo->cinfo, COL_RES_DL_SRC))
1469 col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DTE");
1473 /* Traffic from DCE to DTE. */
1474 if (check_col(pinfo->cinfo, COL_RES_DL_DST))
1475 col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DTE");
1476 if (check_col(pinfo->cinfo, COL_RES_DL_SRC))
1477 col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DCE");
1481 if (check_col(pinfo->cinfo, COL_INFO)) {
1482 if (pinfo->pseudo_header->atm.aal == AAL_5) {
1483 col_add_fstr(pinfo->cinfo, COL_INFO, "AAL5 %s",
1484 val_to_str(pinfo->pseudo_header->atm.type, aal5_hltype_vals,
1485 "Unknown traffic type (%u)"));
1487 col_add_str(pinfo->cinfo, COL_INFO,
1488 val_to_str(pinfo->pseudo_header->atm.aal, aal_vals,
1489 "Unknown AAL (%u)"));
1494 ti = proto_tree_add_protocol_format(tree, proto_atm, tvb, 0, 0, "ATM");
1495 atm_tree = proto_item_add_subtree(ti, ett_atm);
1497 switch (pinfo->pseudo_header->atm.channel) {
1500 /* Traffic from DTE to DCE. */
1501 proto_tree_add_text(atm_tree, tvb, 0, 0, "Channel: DTE->DCE");
1505 /* Traffic from DCE to DTE. */
1506 proto_tree_add_text(atm_tree, tvb, 0, 0, "Channel: DCE->DTE");
1510 /* Sniffers shouldn't provide anything other than 0 or 1. */
1511 proto_tree_add_text(atm_tree, tvb, 0, 0, "Channel: %u",
1512 pinfo->pseudo_header->atm.channel);
1516 proto_tree_add_uint_format(atm_tree, hf_atm_aal, tvb, 0, 0,
1517 pinfo->pseudo_header->atm.aal,
1519 val_to_str(pinfo->pseudo_header->atm.aal, aal_vals,
1520 "Unknown AAL (%u)"));
1522 if (pinfo->pseudo_header->atm.flags & ATM_RAW_CELL) {
1523 /* This is a single cell, with the cell header at the beginning. */
1524 proto_item_set_len(ti, 5);
1525 dissect_atm_cell(tvb, pinfo, tree, atm_tree);
1527 /* This is a reassembled PDU. */
1528 dissect_reassembled_pdu(tvb, pinfo, tree, atm_tree, truncated);
1533 dissect_atm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1535 dissect_atm_common(tvb, pinfo, tree, TRUE);
1539 dissect_atm_untruncated(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1541 dissect_atm_common(tvb, pinfo, tree, FALSE);
1545 proto_register_atm(void)
1547 static hf_register_info hf[] = {
1549 { "AAL", "atm.aal", FT_UINT8, BASE_DEC, VALS(aal_vals), 0x0,
1553 { "VPI", "atm.vpi", FT_UINT8, BASE_DEC, NULL, 0x0,
1557 { "VCI", "atm.vci", FT_UINT16, BASE_DEC, NULL, 0x0,
1560 static gint *ett[] = {
1567 &ett_atm_lane_lc_lan_dest,
1568 &ett_atm_lane_lc_lan_dest_rd,
1569 &ett_atm_lane_lc_flags,
1570 &ett_atm_lane_lc_tlv,
1572 proto_atm = proto_register_protocol("ATM", "ATM", "atm");
1573 proto_aal1 = proto_register_protocol("ATM AAL1", "AAL1", "aal1");
1574 proto_aal3_4 = proto_register_protocol("ATM AAL3/4", "AAL3_4", "aal3_4");
1575 proto_oamaal = proto_register_protocol("ATM OAM AAL", "OAM AAL", "oamaal");
1576 proto_register_field_array(proto_atm, hf, array_length(hf));
1577 proto_register_subtree_array(ett, array_length(ett));
1579 proto_ilmi = proto_register_protocol("ILMI", "ILMI", "ilmi");
1581 register_dissector("ilmi", dissect_ilmi, proto_ilmi);
1583 proto_atm_lane = proto_register_protocol("ATM LAN Emulation",
1584 "ATM LANE", "lane");
1586 register_dissector("lane", dissect_lane, proto_atm_lane);
1590 proto_reg_handoff_atm(void)
1592 dissector_handle_t atm_handle, atm_untruncated_handle;
1595 * Get handles for the Ethernet, Token Ring, LLC, SSCOP, LANE,
1596 * and ILMI dissectors.
1598 eth_handle = find_dissector("eth");
1599 tr_handle = find_dissector("tr");
1600 llc_handle = find_dissector("llc");
1601 sscop_handle = find_dissector("sscop");
1602 lane_handle = find_dissector("lane");
1603 ilmi_handle = find_dissector("ilmi");
1604 data_handle = find_dissector("data");
1606 atm_handle = create_dissector_handle(dissect_atm, proto_atm);
1607 dissector_add("wtap_encap", WTAP_ENCAP_ATM_PDUS, atm_handle);
1609 atm_untruncated_handle = create_dissector_handle(dissect_atm_untruncated,
1611 dissector_add("wtap_encap", WTAP_ENCAP_ATM_PDUS_UNTRUNCATED,
1612 atm_untruncated_handle);