2 * Routines for ATM packet disassembly
4 * $Id: packet-atm.c,v 1.65 2003/09/06 01:21:00 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, proto_ilmi, ett_ilmi, FALSE);
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);
1017 * Check for sanity in the AAL5 length. It must be > 0
1018 * and must be less than the amount of space left after
1019 * we remove the trailer.
1021 * If it's not sane, assume we don't have a trailer.
1023 if (aal5_length > 0 && aal5_length <= length - 8) {
1025 * How much padding is there?
1027 pad_length = length - aal5_length - 8;
1030 * There is no reason for more than 47 bytes of padding.
1031 * The most padding you can have would be 7 bytes at the
1032 * end of the next-to-last cell (8 bytes after the end of
1033 * the data means you can fit the trailer in that cell),
1034 * plus 40 bytes in the last cell (with the last 8 bytes
1037 * If there's more than 47 bytes of padding, assume we don't
1040 if (pad_length <= 47) {
1042 if (pad_length > 0) {
1043 proto_tree_add_text(atm_tree, tvb, aal5_length, pad_length,
1046 proto_tree_add_text(atm_tree, tvb, length - 8, 1, "AAL5 UU: 0x%02x",
1047 tvb_get_guint8(tvb, length - 8));
1048 proto_tree_add_text(atm_tree, tvb, length - 7, 1, "AAL5 CPI: 0x%02x",
1049 tvb_get_guint8(tvb, length - 7));
1050 proto_tree_add_text(atm_tree, tvb, length - 6, 2, "AAL5 len: %u",
1052 crc = tvb_get_ntohl(tvb, length - 4);
1053 calc_crc = update_crc(0xFFFFFFFF, tvb_get_ptr(tvb, 0, length),
1055 proto_tree_add_text(atm_tree, tvb, length - 4, 4,
1056 "AAL5 CRC: 0x%08X (%s)", crc,
1057 (calc_crc == 0xC704DD7B) ? "correct" : "incorrect");
1059 next_tvb = tvb_new_subset(tvb, 0, aal5_length, aal5_length);
1065 switch (pinfo->pseudo_header->atm.aal) {
1067 case AAL_SIGNALLING:
1068 call_dissector(sscop_handle, next_tvb, pinfo, tree);
1072 switch (pinfo->pseudo_header->atm.type) {
1075 call_dissector(llc_handle, next_tvb, pinfo, tree);
1079 call_dissector(lane_handle, next_tvb, pinfo, tree);
1083 call_dissector(ilmi_handle, next_tvb, pinfo, tree);
1088 /* Dump it as raw data. */
1089 call_dissector(data_handle, next_tvb, pinfo, tree);
1097 /* Dump it as raw data. */
1098 call_dissector(data_handle, next_tvb, pinfo, tree);
1105 * Charles Michael Heard's HEC code, from
1107 * http://cell-relay.indiana.edu/cell-relay/publications/software/CRC/32bitCRC.tutorial.html
1109 * with the syndrome and error position tables initialized with values
1110 * computed by his "gen_syndrome_table()" and "gen_err_posn_table()" routines,
1111 * rather than by calling those routines at run time, and with various data
1112 * type cleanups and changes not to correct the header if a correctible
1113 * error was detected.
1115 #define COSET_LEADER 0x055 /* x^6 + x^4 + x^2 + 1 */
1117 static const guint8 syndrome_table[256] = {
1118 0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15,
1119 0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d,
1120 0x70, 0x77, 0x7e, 0x79, 0x6c, 0x6b, 0x62, 0x65,
1121 0x48, 0x4f, 0x46, 0x41, 0x54, 0x53, 0x5a, 0x5d,
1122 0xe0, 0xe7, 0xee, 0xe9, 0xfc, 0xfb, 0xf2, 0xf5,
1123 0xd8, 0xdf, 0xd6, 0xd1, 0xc4, 0xc3, 0xca, 0xcd,
1124 0x90, 0x97, 0x9e, 0x99, 0x8c, 0x8b, 0x82, 0x85,
1125 0xa8, 0xaf, 0xa6, 0xa1, 0xb4, 0xb3, 0xba, 0xbd,
1126 0xc7, 0xc0, 0xc9, 0xce, 0xdb, 0xdc, 0xd5, 0xd2,
1127 0xff, 0xf8, 0xf1, 0xf6, 0xe3, 0xe4, 0xed, 0xea,
1128 0xb7, 0xb0, 0xb9, 0xbe, 0xab, 0xac, 0xa5, 0xa2,
1129 0x8f, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9d, 0x9a,
1130 0x27, 0x20, 0x29, 0x2e, 0x3b, 0x3c, 0x35, 0x32,
1131 0x1f, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0d, 0x0a,
1132 0x57, 0x50, 0x59, 0x5e, 0x4b, 0x4c, 0x45, 0x42,
1133 0x6f, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7d, 0x7a,
1134 0x89, 0x8e, 0x87, 0x80, 0x95, 0x92, 0x9b, 0x9c,
1135 0xb1, 0xb6, 0xbf, 0xb8, 0xad, 0xaa, 0xa3, 0xa4,
1136 0xf9, 0xfe, 0xf7, 0xf0, 0xe5, 0xe2, 0xeb, 0xec,
1137 0xc1, 0xc6, 0xcf, 0xc8, 0xdd, 0xda, 0xd3, 0xd4,
1138 0x69, 0x6e, 0x67, 0x60, 0x75, 0x72, 0x7b, 0x7c,
1139 0x51, 0x56, 0x5f, 0x58, 0x4d, 0x4a, 0x43, 0x44,
1140 0x19, 0x1e, 0x17, 0x10, 0x05, 0x02, 0x0b, 0x0c,
1141 0x21, 0x26, 0x2f, 0x28, 0x3d, 0x3a, 0x33, 0x34,
1142 0x4e, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5c, 0x5b,
1143 0x76, 0x71, 0x78, 0x7f, 0x6a, 0x6d, 0x64, 0x63,
1144 0x3e, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2c, 0x2b,
1145 0x06, 0x01, 0x08, 0x0f, 0x1a, 0x1d, 0x14, 0x13,
1146 0xae, 0xa9, 0xa0, 0xa7, 0xb2, 0xb5, 0xbc, 0xbb,
1147 0x96, 0x91, 0x98, 0x9f, 0x8a, 0x8d, 0x84, 0x83,
1148 0xde, 0xd9, 0xd0, 0xd7, 0xc2, 0xc5, 0xcc, 0xcb,
1149 0xe6, 0xe1, 0xe8, 0xef, 0xfa, 0xfd, 0xf4, 0xf3,
1152 #define NO_ERROR_DETECTED -128
1153 #define UNCORRECTIBLE_ERROR 128
1155 static const int err_posn_table[256] = {
1156 NO_ERROR_DETECTED, 37,
1157 36, UNCORRECTIBLE_ERROR,
1158 35, UNCORRECTIBLE_ERROR,
1159 UNCORRECTIBLE_ERROR, 29,
1160 34, UNCORRECTIBLE_ERROR,
1161 UNCORRECTIBLE_ERROR, 6,
1162 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1163 28, UNCORRECTIBLE_ERROR,
1164 33, UNCORRECTIBLE_ERROR,
1165 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1166 UNCORRECTIBLE_ERROR, 21,
1167 5, UNCORRECTIBLE_ERROR,
1168 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1169 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1170 27, UNCORRECTIBLE_ERROR,
1171 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1172 32, UNCORRECTIBLE_ERROR,
1173 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1174 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1175 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1176 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1177 20, UNCORRECTIBLE_ERROR,
1178 4, UNCORRECTIBLE_ERROR,
1179 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1180 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1181 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1182 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1183 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1184 26, UNCORRECTIBLE_ERROR,
1185 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1186 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1187 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1191 * Return an indication of whether there was an error in the cell header
1192 * and, if so, where the error was, if it was correctable.
1195 get_header_err(const guint8 *cell_header)
1197 register guint8 syndrome;
1198 register int i, err_posn;
1201 for (i = 0; i < 4; i++)
1202 syndrome = syndrome_table[syndrome ^ cell_header[i]];
1203 syndrome ^= cell_header[4] ^ COSET_LEADER;
1205 err_posn = err_posn_table [syndrome];
1208 return NO_ERROR_DETECTED;
1209 else if (err_posn < 40)
1212 return UNCORRECTIBLE_ERROR;
1215 static const value_string pt_vals[] = {
1216 { 0, "User data cell, congestion not experienced, SDU-type = 0" },
1217 { 1, "User data cell, congestion not experienced, SDU-type = 1" },
1218 { 2, "User data cell, congestion experienced, SDU-type = 0" },
1219 { 3, "User data cell, congestion experienced, SDU-type = 1" },
1220 { 4, "Segment OAM F5 flow related cell" },
1221 { 5, "End-to-end OAM F5 flow related cell" },
1226 * Charles Michael Heard's CRC-10 code, from
1228 * http://cell-relay.indiana.edu/cell-relay/publications/software/CRC/crc10.html
1230 * with the CRC table initialized with values computed by
1231 * his "gen_byte_crc10_table()" routine, rather than by calling that
1232 * routine at run time, and with various data type cleanups.
1234 static const guint16 byte_crc10_table[256] = {
1235 0x0000, 0x0233, 0x0255, 0x0066, 0x0299, 0x00aa, 0x00cc, 0x02ff,
1236 0x0301, 0x0132, 0x0154, 0x0367, 0x0198, 0x03ab, 0x03cd, 0x01fe,
1237 0x0031, 0x0202, 0x0264, 0x0057, 0x02a8, 0x009b, 0x00fd, 0x02ce,
1238 0x0330, 0x0103, 0x0165, 0x0356, 0x01a9, 0x039a, 0x03fc, 0x01cf,
1239 0x0062, 0x0251, 0x0237, 0x0004, 0x02fb, 0x00c8, 0x00ae, 0x029d,
1240 0x0363, 0x0150, 0x0136, 0x0305, 0x01fa, 0x03c9, 0x03af, 0x019c,
1241 0x0053, 0x0260, 0x0206, 0x0035, 0x02ca, 0x00f9, 0x009f, 0x02ac,
1242 0x0352, 0x0161, 0x0107, 0x0334, 0x01cb, 0x03f8, 0x039e, 0x01ad,
1243 0x00c4, 0x02f7, 0x0291, 0x00a2, 0x025d, 0x006e, 0x0008, 0x023b,
1244 0x03c5, 0x01f6, 0x0190, 0x03a3, 0x015c, 0x036f, 0x0309, 0x013a,
1245 0x00f5, 0x02c6, 0x02a0, 0x0093, 0x026c, 0x005f, 0x0039, 0x020a,
1246 0x03f4, 0x01c7, 0x01a1, 0x0392, 0x016d, 0x035e, 0x0338, 0x010b,
1247 0x00a6, 0x0295, 0x02f3, 0x00c0, 0x023f, 0x000c, 0x006a, 0x0259,
1248 0x03a7, 0x0194, 0x01f2, 0x03c1, 0x013e, 0x030d, 0x036b, 0x0158,
1249 0x0097, 0x02a4, 0x02c2, 0x00f1, 0x020e, 0x003d, 0x005b, 0x0268,
1250 0x0396, 0x01a5, 0x01c3, 0x03f0, 0x010f, 0x033c, 0x035a, 0x0169,
1251 0x0188, 0x03bb, 0x03dd, 0x01ee, 0x0311, 0x0122, 0x0144, 0x0377,
1252 0x0289, 0x00ba, 0x00dc, 0x02ef, 0x0010, 0x0223, 0x0245, 0x0076,
1253 0x01b9, 0x038a, 0x03ec, 0x01df, 0x0320, 0x0113, 0x0175, 0x0346,
1254 0x02b8, 0x008b, 0x00ed, 0x02de, 0x0021, 0x0212, 0x0274, 0x0047,
1255 0x01ea, 0x03d9, 0x03bf, 0x018c, 0x0373, 0x0140, 0x0126, 0x0315,
1256 0x02eb, 0x00d8, 0x00be, 0x028d, 0x0072, 0x0241, 0x0227, 0x0014,
1257 0x01db, 0x03e8, 0x038e, 0x01bd, 0x0342, 0x0171, 0x0117, 0x0324,
1258 0x02da, 0x00e9, 0x008f, 0x02bc, 0x0043, 0x0270, 0x0216, 0x0025,
1259 0x014c, 0x037f, 0x0319, 0x012a, 0x03d5, 0x01e6, 0x0180, 0x03b3,
1260 0x024d, 0x007e, 0x0018, 0x022b, 0x00d4, 0x02e7, 0x0281, 0x00b2,
1261 0x017d, 0x034e, 0x0328, 0x011b, 0x03e4, 0x01d7, 0x01b1, 0x0382,
1262 0x027c, 0x004f, 0x0029, 0x021a, 0x00e5, 0x02d6, 0x02b0, 0x0083,
1263 0x012e, 0x031d, 0x037b, 0x0148, 0x03b7, 0x0184, 0x01e2, 0x03d1,
1264 0x022f, 0x001c, 0x007a, 0x0249, 0x00b6, 0x0285, 0x02e3, 0x00d0,
1265 0x011f, 0x032c, 0x034a, 0x0179, 0x0386, 0x01b5, 0x01d3, 0x03e0,
1266 0x021e, 0x002d, 0x004b, 0x0278, 0x0087, 0x02b4, 0x02d2, 0x00e1,
1269 /* update the data block's CRC-10 remainder one byte at a time */
1271 update_crc10_by_bytes(guint16 crc10_accum, const guint8 *data_blk_ptr,
1276 for (i = 0; i < data_blk_size; i++) {
1277 crc10_accum = ((crc10_accum << 8) & 0x3ff)
1278 ^ byte_crc10_table[( crc10_accum >> 2) & 0xff]
1284 static const value_string st_vals[] = {
1292 #define OAM_TYPE_FM 1 /* Fault Management */
1293 #define OAM_TYPE_PM 2 /* Performance Management */
1294 #define OAM_TYPE_AD 8 /* Activation/Deactivation */
1296 static const value_string oam_type_vals[] = {
1297 { OAM_TYPE_FM, "Fault Management" },
1298 { OAM_TYPE_PM, "Performance Management" },
1299 { OAM_TYPE_AD, "Activation/Deactivation" },
1303 static const value_string ft_fm_vals[] = {
1304 { 0, "Alarm Indication Signal" },
1305 { 1, "Far End Receive Failure" },
1306 { 8, "OAM Cell Loopback" },
1307 { 4, "Continuity Check" },
1311 static const value_string ft_pm_vals[] = {
1312 { 0, "Forward Monitoring" },
1313 { 1, "Backward Reporting" },
1314 { 2, "Monitoring and Reporting" },
1318 static const value_string ft_ad_vals[] = {
1319 { 0, "Performance Monitoring" },
1320 { 1, "Continuity Check" },
1325 dissect_atm_cell(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1326 proto_tree *atm_tree)
1329 proto_tree *aal_tree;
1335 guint16 aal3_4_hdr, aal3_4_trlr;
1341 octet = tvb_get_guint8(tvb, 0);
1342 proto_tree_add_text(atm_tree, tvb, 0, 1, "GFC: 0x%x", octet >> 4);
1343 vpi = (octet & 0xF0) << 4;
1344 octet = tvb_get_guint8(tvb, 1);
1346 proto_tree_add_uint(atm_tree, hf_atm_vpi, tvb, 0, 2, vpi);
1347 vci = (octet & 0x0F) << 12;
1348 octet = tvb_get_guint8(tvb, 2);
1350 octet = tvb_get_guint8(tvb, 3);
1352 proto_tree_add_uint(atm_tree, hf_atm_vci, tvb, 1, 3, vci);
1353 proto_tree_add_text(atm_tree, tvb, 3, 1, "Payload Type: %s",
1354 val_to_str((octet >> 1) & 0x7, pt_vals, "Unknown (%u)"));
1355 proto_tree_add_text(atm_tree, tvb, 3, 1, "Cell Loss Priority: %s",
1356 (octet & 0x01) ? "Low priority" : "High priority");
1357 ti = proto_tree_add_text(atm_tree, tvb, 4, 1, "Header Error Check: 0x%02x",
1358 tvb_get_guint8(tvb, 4));
1359 err = get_header_err(tvb_get_ptr(tvb, 0, 5));
1360 if (err == NO_ERROR_DETECTED)
1361 proto_item_append_text(ti, " (correct)");
1362 else if (err == UNCORRECTIBLE_ERROR)
1363 proto_item_append_text(ti, " (uncorrectable error)");
1365 proto_item_append_text(ti, " (error in bit %d)", err);
1368 switch (pinfo->pseudo_header->atm.aal) {
1371 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1372 col_set_str(pinfo->cinfo, COL_PROTOCOL, "AAL1");
1373 ti = proto_tree_add_item(tree, proto_aal1, tvb, offset, -1, FALSE);
1374 aal_tree = proto_item_add_subtree(ti, ett_aal1);
1375 octet = tvb_get_guint8(tvb, offset);
1376 proto_tree_add_text(aal_tree, tvb, offset, 1, "CSI: %u", octet >> 7);
1377 proto_tree_add_text(aal_tree, tvb, offset, 1, "Sequence Count: %u",
1378 (octet >> 4) & 0x7);
1379 if (check_col(pinfo->cinfo, COL_INFO)) {
1380 col_add_fstr(pinfo->cinfo, COL_INFO, "Sequence count = %u",
1381 (octet >> 4) & 0x7);
1383 proto_tree_add_text(aal_tree, tvb, offset, 1, "CRC: 0x%x",
1384 (octet >> 1) & 0x7);
1385 proto_tree_add_text(aal_tree, tvb, offset, 1, "Parity: %u",
1389 proto_tree_add_text(aal_tree, tvb, offset, 47, "Payload");
1394 * XXX - or should this be the CS PDU?
1396 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1397 col_set_str(pinfo->cinfo, COL_PROTOCOL, "AAL3/4");
1398 ti = proto_tree_add_item(tree, proto_aal3_4, tvb, offset, -1, FALSE);
1399 aal_tree = proto_item_add_subtree(ti, ett_aal3_4);
1400 aal3_4_hdr = tvb_get_ntohs(tvb, offset);
1401 if (check_col(pinfo->cinfo, COL_INFO)) {
1402 col_add_fstr(pinfo->cinfo, COL_INFO, "%s, sequence number = %u",
1403 val_to_str(aal3_4_hdr >> 14, st_vals, "Unknown (%u)"),
1404 (aal3_4_hdr >> 10) & 0xF);
1406 proto_tree_add_text(aal_tree, tvb, offset, 2, "Segment Type: %s",
1407 val_to_str(aal3_4_hdr >> 14, st_vals, "Unknown (%u)"));
1408 proto_tree_add_text(aal_tree, tvb, offset, 2, "Sequence Number: %u",
1409 (aal3_4_hdr >> 10) & 0xF);
1410 proto_tree_add_text(aal_tree, tvb, offset, 2, "Multiplex ID: %u",
1411 aal3_4_hdr & 0x3FF);
1414 proto_tree_add_text(aal_tree, tvb, offset, 44, "Information");
1417 aal3_4_trlr = tvb_get_ntohs(tvb, offset);
1418 proto_tree_add_text(aal_tree, tvb, offset, 2, "Length Indicator: %u",
1419 (aal3_4_trlr >> 10) & 0x3F);
1420 length = tvb_length_remaining(tvb, 5);
1421 crc10 = update_crc10_by_bytes(0, tvb_get_ptr(tvb, 5, length),
1423 proto_tree_add_text(aal_tree, tvb, offset, 2, "CRC: 0x%03x (%s)",
1424 aal3_4_trlr & 0x3FF,
1425 (crc10 == 0) ? "correct" : "incorrect");
1429 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1430 col_set_str(pinfo->cinfo, COL_PROTOCOL, "OAM AAL");
1431 ti = proto_tree_add_item(tree, proto_oamaal, tvb, offset, -1, FALSE);
1432 aal_tree = proto_item_add_subtree(ti, ett_oamaal);
1433 octet = tvb_get_guint8(tvb, offset);
1434 proto_tree_add_text(aal_tree, tvb, offset, 1, "OAM Type: %s",
1435 val_to_str(octet >> 4, oam_type_vals, "Unknown (%u)"));
1436 switch (octet >> 4) {
1439 proto_tree_add_text(aal_tree, tvb, offset, 1, "Function Type: %s",
1440 val_to_str(octet & 0x0F, ft_fm_vals, "Unknown (%u)"));
1444 proto_tree_add_text(aal_tree, tvb, offset, 1, "Function Type: %s",
1445 val_to_str(octet & 0x0F, ft_pm_vals, "Unknown (%u)"));
1449 proto_tree_add_text(aal_tree, tvb, offset, 1, "Function Type: %s",
1450 val_to_str(octet & 0x0F, ft_ad_vals, "Unknown (%u)"));
1454 proto_tree_add_text(aal_tree, tvb, offset, 1, "Function Type: %u",
1460 proto_tree_add_text(aal_tree, tvb, offset, 45, "Function-specific information");
1463 length = tvb_length_remaining(tvb, 5);
1464 crc10 = update_crc10_by_bytes(0, tvb_get_ptr(tvb, 5, length),
1466 oam_crc = tvb_get_ntohs(tvb, offset);
1467 proto_tree_add_text(aal_tree, tvb, offset, 2, "CRC-10: 0x%03x (%s)",
1469 (crc10 == 0) ? "correct" : "incorrect");
1473 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
1474 call_dissector(data_handle, next_tvb, pinfo, tree);
1480 dissect_atm_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1483 proto_tree *atm_tree = NULL;
1484 proto_item *ti = NULL;
1486 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1487 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATM");
1489 switch (pinfo->pseudo_header->atm.channel) {
1492 /* Traffic from DTE to DCE. */
1493 if (check_col(pinfo->cinfo, COL_RES_DL_DST))
1494 col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DCE");
1495 if (check_col(pinfo->cinfo, COL_RES_DL_SRC))
1496 col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DTE");
1500 /* Traffic from DCE to DTE. */
1501 if (check_col(pinfo->cinfo, COL_RES_DL_DST))
1502 col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DTE");
1503 if (check_col(pinfo->cinfo, COL_RES_DL_SRC))
1504 col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DCE");
1508 if (check_col(pinfo->cinfo, COL_INFO)) {
1509 if (pinfo->pseudo_header->atm.aal == AAL_5) {
1510 col_add_fstr(pinfo->cinfo, COL_INFO, "AAL5 %s",
1511 val_to_str(pinfo->pseudo_header->atm.type, aal5_hltype_vals,
1512 "Unknown traffic type (%u)"));
1514 col_add_str(pinfo->cinfo, COL_INFO,
1515 val_to_str(pinfo->pseudo_header->atm.aal, aal_vals,
1516 "Unknown AAL (%u)"));
1521 ti = proto_tree_add_protocol_format(tree, proto_atm, tvb, 0, 0, "ATM");
1522 atm_tree = proto_item_add_subtree(ti, ett_atm);
1524 switch (pinfo->pseudo_header->atm.channel) {
1527 /* Traffic from DTE to DCE. */
1528 proto_tree_add_text(atm_tree, tvb, 0, 0, "Channel: DTE->DCE");
1532 /* Traffic from DCE to DTE. */
1533 proto_tree_add_text(atm_tree, tvb, 0, 0, "Channel: DCE->DTE");
1537 /* Sniffers shouldn't provide anything other than 0 or 1. */
1538 proto_tree_add_text(atm_tree, tvb, 0, 0, "Channel: %u",
1539 pinfo->pseudo_header->atm.channel);
1543 proto_tree_add_uint_format(atm_tree, hf_atm_aal, tvb, 0, 0,
1544 pinfo->pseudo_header->atm.aal,
1546 val_to_str(pinfo->pseudo_header->atm.aal, aal_vals,
1547 "Unknown AAL (%u)"));
1549 if (pinfo->pseudo_header->atm.flags & ATM_RAW_CELL) {
1550 /* This is a single cell, with the cell header at the beginning. */
1551 proto_item_set_len(ti, 5);
1552 dissect_atm_cell(tvb, pinfo, tree, atm_tree);
1554 /* This is a reassembled PDU. */
1555 dissect_reassembled_pdu(tvb, pinfo, tree, atm_tree, truncated);
1560 dissect_atm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1562 dissect_atm_common(tvb, pinfo, tree, TRUE);
1566 dissect_atm_untruncated(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1568 dissect_atm_common(tvb, pinfo, tree, FALSE);
1572 proto_register_atm(void)
1574 static hf_register_info hf[] = {
1576 { "AAL", "atm.aal", FT_UINT8, BASE_DEC, VALS(aal_vals), 0x0,
1580 { "VPI", "atm.vpi", FT_UINT8, BASE_DEC, NULL, 0x0,
1584 { "VCI", "atm.vci", FT_UINT16, BASE_DEC, NULL, 0x0,
1587 static gint *ett[] = {
1594 &ett_atm_lane_lc_lan_dest,
1595 &ett_atm_lane_lc_lan_dest_rd,
1596 &ett_atm_lane_lc_flags,
1597 &ett_atm_lane_lc_tlv,
1599 proto_atm = proto_register_protocol("ATM", "ATM", "atm");
1600 proto_aal1 = proto_register_protocol("ATM AAL1", "AAL1", "aal1");
1601 proto_aal3_4 = proto_register_protocol("ATM AAL3/4", "AAL3_4", "aal3_4");
1602 proto_oamaal = proto_register_protocol("ATM OAM AAL", "OAM AAL", "oamaal");
1603 proto_register_field_array(proto_atm, hf, array_length(hf));
1604 proto_register_subtree_array(ett, array_length(ett));
1606 proto_ilmi = proto_register_protocol("ILMI", "ILMI", "ilmi");
1608 register_dissector("ilmi", dissect_ilmi, proto_ilmi);
1610 proto_atm_lane = proto_register_protocol("ATM LAN Emulation",
1611 "ATM LANE", "lane");
1613 register_dissector("lane", dissect_lane, proto_atm_lane);
1617 proto_reg_handoff_atm(void)
1619 dissector_handle_t atm_handle, atm_untruncated_handle;
1622 * Get handles for the Ethernet, Token Ring, LLC, SSCOP, LANE,
1623 * and ILMI dissectors.
1625 eth_handle = find_dissector("eth");
1626 tr_handle = find_dissector("tr");
1627 llc_handle = find_dissector("llc");
1628 sscop_handle = find_dissector("sscop");
1629 lane_handle = find_dissector("lane");
1630 ilmi_handle = find_dissector("ilmi");
1631 data_handle = find_dissector("data");
1633 atm_handle = create_dissector_handle(dissect_atm, proto_atm);
1634 dissector_add("wtap_encap", WTAP_ENCAP_ATM_PDUS, atm_handle);
1636 atm_untruncated_handle = create_dissector_handle(dissect_atm_untruncated,
1638 dissector_add("wtap_encap", WTAP_ENCAP_ATM_PDUS_UNTRUNCATED,
1639 atm_untruncated_handle);