2 * Routines for ATM packet disassembly
4 * $Id: packet-atm.c,v 1.53 2003/01/09 01:55:11 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 dissect_reassembled_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
793 proto_tree *atm_tree, gboolean truncated)
795 guint length, reported_length;
801 * This is reassembled traffic, so the cell headers are missing;
802 * show the VPI and VCI from the pseudo-header.
804 proto_tree_add_uint(atm_tree, hf_atm_vpi, tvb, 0, 0,
805 pinfo->pseudo_header->atm.vpi);
806 proto_tree_add_uint(atm_tree, hf_atm_vci, tvb, 0, 0,
807 pinfo->pseudo_header->atm.vci);
808 if (pinfo->pseudo_header->atm.aal == AAL_5) {
809 proto_tree_add_text(atm_tree, tvb, 0, 0, "Traffic type: %s",
810 val_to_str(pinfo->pseudo_header->atm.type, aal5_hltype_vals,
811 "Unknown AAL5 traffic type (%u)"));
812 switch (pinfo->pseudo_header->atm.type) {
815 proto_tree_add_text(atm_tree, tvb, 0, 0, "VC multiplexed traffic type: %s",
816 val_to_str(pinfo->pseudo_header->atm.subtype,
817 vcmx_type_vals, "Unknown VCMX traffic type (%u)"));
821 proto_tree_add_text(atm_tree, tvb, 0, 0, "LANE traffic type: %s",
822 val_to_str(pinfo->pseudo_header->atm.subtype,
823 lane_type_vals, "Unknown LANE traffic type (%u)"));
827 proto_tree_add_text(atm_tree, tvb, 0, 0, "Ipsilon traffic type: %s",
828 val_to_str(pinfo->pseudo_header->atm.subtype,
829 ipsilon_type_vals, "Unknown Ipsilon traffic type (%u)"));
837 * The packet data does not include stuff such as the AAL5
840 if (pinfo->pseudo_header->atm.cells != 0) {
842 * If the cell count is 0, assume it means we don't know how
845 * XXX - also assume it means we don't know what was in the AAL5
846 * trailer. We may, however, find some capture program that can
847 * give us the AAL5 trailer information but not the cell count,
848 * in which case we need some other way of indicating whether we
849 * have the AAL5 trailer information.
852 proto_tree_add_text(atm_tree, tvb, 0, 0, "Cells: %u",
853 pinfo->pseudo_header->atm.cells);
854 proto_tree_add_text(atm_tree, tvb, 0, 0, "AAL5 UU: 0x%02x",
855 pinfo->pseudo_header->atm.aal5t_u2u >> 8);
856 proto_tree_add_text(atm_tree, tvb, 0, 0, "AAL5 CPI: 0x%02x",
857 pinfo->pseudo_header->atm.aal5t_u2u & 0xFF);
858 proto_tree_add_text(atm_tree, tvb, 0, 0, "AAL5 len: %u",
859 pinfo->pseudo_header->atm.aal5t_len);
860 proto_tree_add_text(atm_tree, tvb, 0, 0, "AAL5 checksum: 0x%08X",
861 pinfo->pseudo_header->atm.aal5t_chksum);
866 * The packet data includes stuff such as the AAL5 trailer, if
867 * it wasn't cut off by the snapshot length.
868 * Decode the trailer, if present, and then chop it off.
870 length = tvb_length(tvb);
871 reported_length = tvb_reported_length(tvb);
872 if ((reported_length % 48) == 0) {
874 * Reported length is a multiple of 48, so we can presumably
875 * divide it by 48 to get the number of cells.
877 proto_tree_add_text(atm_tree, tvb, 0, 0, "Cells: %u",
880 if (length >= reported_length) {
882 * XXX - what if the packet is truncated? Can that happen?
883 * What if you capture with Windows Sniffer on an ATM link
884 * and tell it not to save the entire packet? What happens
887 aal5_length = tvb_get_ntohs(tvb, length - 6);
889 pad_length = length - aal5_length - 8;
890 if (pad_length > 0) {
891 proto_tree_add_text(atm_tree, tvb, aal5_length, pad_length,
894 proto_tree_add_text(atm_tree, tvb, length - 8, 1, "AAL5 UU: 0x%02x",
895 tvb_get_guint8(tvb, length - 8));
896 proto_tree_add_text(atm_tree, tvb, length - 7, 1, "AAL5 CPI: 0x%02x",
897 tvb_get_guint8(tvb, length - 7));
898 proto_tree_add_text(atm_tree, tvb, length - 6, 2, "AAL5 len: %u",
901 * XXX - check the checksum.
903 proto_tree_add_text(atm_tree, tvb, length - 4, 4, "AAL5 checksum: 0x%08X",
904 tvb_get_ntohl(tvb, length - 4));
906 next_tvb = tvb_new_subset(tvb, 0, aal5_length, aal5_length);
910 switch (pinfo->pseudo_header->atm.aal) {
913 call_dissector(sscop_handle, next_tvb, pinfo, tree);
917 switch (pinfo->pseudo_header->atm.type) {
920 call_dissector(llc_handle, next_tvb, pinfo, tree);
924 call_dissector(lane_handle, next_tvb, pinfo, tree);
928 call_dissector(ilmi_handle, next_tvb, pinfo, tree);
933 /* Dump it as raw data. */
934 call_dissector(data_handle, next_tvb, pinfo, tree);
942 static const value_string pt_vals[] = {
943 { 0, "User data cell, congestion not experienced, SDU-type = 0" },
944 { 1, "User data cell, congestion not experienced, SDU-type = 1" },
945 { 2, "User data cell, congestion experienced, SDU-type = 0" },
946 { 3, "User data cell, congestion experienced, SDU-type = 1" },
947 { 4, "Segment OAM F5 flow related cell" },
948 { 5, "End-to-end OAM F5 flow related cell" },
952 static const value_string st_vals[] = {
960 #define OAM_TYPE_FM 1 /* Fault Management */
961 #define OAM_TYPE_PM 2 /* Performance Management */
962 #define OAM_TYPE_AD 8 /* Activation/Deactivation */
964 static const value_string oam_type_vals[] = {
965 { OAM_TYPE_FM, "Fault Management" },
966 { OAM_TYPE_PM, "Performance Management" },
967 { OAM_TYPE_AD, "Activation/Deactivation" },
971 static const value_string ft_fm_vals[] = {
972 { 0, "Alarm Indication Signal" },
973 { 1, "Far End Receive Failure" },
974 { 8, "OAM Cell Loopback" },
975 { 4, "Continuity Check" },
979 static const value_string ft_pm_vals[] = {
980 { 0, "Forward Monitoring" },
981 { 1, "Backward Reporting" },
982 { 2, "Monitoring and Reporting" },
986 static const value_string ft_ad_vals[] = {
987 { 0, "Performance Monitoring" },
988 { 1, "Continuity Check" },
993 dissect_atm_cell(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
994 proto_tree *atm_tree)
997 proto_tree *aal_tree;
1002 guint16 aal3_4_hdr, aal3_4_trlr;
1006 octet = tvb_get_guint8(tvb, 0);
1007 proto_tree_add_text(atm_tree, tvb, 0, 1, "GFC: 0x%x", octet >> 4);
1008 vpi = (octet & 0xF0) << 4;
1009 octet = tvb_get_guint8(tvb, 1);
1011 proto_tree_add_uint(atm_tree, hf_atm_vpi, tvb, 0, 2, vpi);
1012 vci = (octet & 0x0F) << 12;
1013 octet = tvb_get_guint8(tvb, 2);
1015 octet = tvb_get_guint8(tvb, 3);
1017 proto_tree_add_uint(atm_tree, hf_atm_vci, tvb, 1, 3, vci);
1018 proto_tree_add_text(atm_tree, tvb, 3, 1, "Payload Type: %s",
1019 val_to_str((octet >> 1) & 0x7, pt_vals, "Unknown (%u)"));
1020 proto_tree_add_text(atm_tree, tvb, 3, 1, "Cell Loss Priority: %s",
1021 (octet & 0x01) ? "Low priority" : "High priority");
1022 proto_tree_add_text(atm_tree, tvb, 4, 1, "Header Error Check: 0x%02x",
1023 tvb_get_guint8(tvb, 4));
1026 switch (pinfo->pseudo_header->atm.aal) {
1029 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1030 col_set_str(pinfo->cinfo, COL_PROTOCOL, "AAL1");
1031 ti = proto_tree_add_item(tree, proto_aal1, tvb, offset, -1, FALSE);
1032 aal_tree = proto_item_add_subtree(ti, ett_aal1);
1033 octet = tvb_get_guint8(tvb, offset);
1034 proto_tree_add_text(aal_tree, tvb, offset, 1, "CSI: %u", octet >> 7);
1035 proto_tree_add_text(aal_tree, tvb, offset, 1, "Sequence Count: %u",
1036 (octet >> 4) & 0x7);
1037 if (check_col(pinfo->cinfo, COL_INFO)) {
1038 col_add_fstr(pinfo->cinfo, COL_INFO, "Sequence count = %u",
1039 (octet >> 4) & 0x7);
1041 proto_tree_add_text(aal_tree, tvb, offset, 1, "CRC: 0x%x",
1042 (octet >> 1) & 0x7);
1043 proto_tree_add_text(aal_tree, tvb, offset, 1, "Parity: %u",
1047 proto_tree_add_text(aal_tree, tvb, offset, 47, "Payload");
1052 * XXX - or should this be the CS PDU?
1054 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1055 col_set_str(pinfo->cinfo, COL_PROTOCOL, "AAL3/4");
1056 ti = proto_tree_add_item(tree, proto_aal3_4, tvb, offset, -1, FALSE);
1057 aal_tree = proto_item_add_subtree(ti, ett_aal3_4);
1058 aal3_4_hdr = tvb_get_ntohs(tvb, offset);
1059 if (check_col(pinfo->cinfo, COL_INFO)) {
1060 col_add_fstr(pinfo->cinfo, COL_INFO, "%s, sequence number = %u",
1061 val_to_str(aal3_4_hdr >> 14, st_vals, "Unknown (%u)"),
1062 (aal3_4_hdr >> 10) & 0xF);
1064 proto_tree_add_text(aal_tree, tvb, offset, 2, "Segment Type: %s",
1065 val_to_str(aal3_4_hdr >> 14, st_vals, "Unknown (%u)"));
1066 proto_tree_add_text(aal_tree, tvb, offset, 2, "Sequence Number: %u",
1067 (aal3_4_hdr >> 10) & 0xF);
1068 proto_tree_add_text(aal_tree, tvb, offset, 2, "Multiplex ID: %u",
1069 aal3_4_hdr & 0x3FF);
1072 proto_tree_add_text(aal_tree, tvb, offset, 44, "Information");
1075 aal3_4_trlr = tvb_get_ntohs(tvb, offset);
1076 proto_tree_add_text(aal_tree, tvb, offset, 2, "Length Indicator: %u",
1077 (aal3_4_trlr >> 10) & 0x3F);
1078 proto_tree_add_text(aal_tree, tvb, offset, 2, "CRC: 0x%03x",
1079 aal3_4_trlr & 0x3FF);
1083 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1084 col_set_str(pinfo->cinfo, COL_PROTOCOL, "OAM AAL");
1085 ti = proto_tree_add_item(tree, proto_oamaal, tvb, offset, -1, FALSE);
1086 aal_tree = proto_item_add_subtree(ti, ett_oamaal);
1087 octet = tvb_get_guint8(tvb, offset);
1088 proto_tree_add_text(aal_tree, tvb, offset, 2, "OAM Type: %s",
1089 val_to_str(octet >> 4, oam_type_vals, "Unknown (%u)"));
1090 switch (octet >> 4) {
1093 proto_tree_add_text(aal_tree, tvb, offset, 2, "Function Type: %s",
1094 val_to_str(octet & 0x0F, ft_fm_vals, "Unknown (%u)"));
1098 proto_tree_add_text(aal_tree, tvb, offset, 2, "Function Type: %s",
1099 val_to_str(octet & 0x0F, ft_pm_vals, "Unknown (%u)"));
1103 proto_tree_add_text(aal_tree, tvb, offset, 2, "Function Type: %s",
1104 val_to_str(octet & 0x0F, ft_ad_vals, "Unknown (%u)"));
1108 proto_tree_add_text(aal_tree, tvb, offset, 2, "Function Type: %u",
1114 proto_tree_add_text(aal_tree, tvb, offset, 45, "Function-specific information");
1117 oam_crc = tvb_get_ntohs(tvb, offset);
1118 proto_tree_add_text(aal_tree, tvb, offset, 2, "CRC-10: 0x%03x",
1123 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
1124 call_dissector(data_handle, next_tvb, pinfo, tree);
1130 dissect_atm_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1133 proto_tree *atm_tree = NULL;
1134 proto_item *ti = NULL;
1136 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1137 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATM");
1139 switch (pinfo->pseudo_header->atm.channel) {
1142 /* Traffic from DTE to DCE. */
1143 if (check_col(pinfo->cinfo, COL_RES_DL_DST))
1144 col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DCE");
1145 if (check_col(pinfo->cinfo, COL_RES_DL_SRC))
1146 col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DTE");
1150 /* Traffic from DCE to DTE. */
1151 if (check_col(pinfo->cinfo, COL_RES_DL_DST))
1152 col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DTE");
1153 if (check_col(pinfo->cinfo, COL_RES_DL_SRC))
1154 col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DCE");
1158 if (check_col(pinfo->cinfo, COL_INFO)) {
1159 if (pinfo->pseudo_header->atm.aal == AAL_5) {
1160 col_add_fstr(pinfo->cinfo, COL_INFO, "AAL5 %s",
1161 val_to_str(pinfo->pseudo_header->atm.type, aal5_hltype_vals,
1162 "Unknown traffic type (%u)"));
1164 col_add_str(pinfo->cinfo, COL_INFO,
1165 val_to_str(pinfo->pseudo_header->atm.aal, aal_vals,
1166 "Unknown AAL (%u)"));
1171 ti = proto_tree_add_protocol_format(tree, proto_atm, tvb, 0, 0, "ATM");
1172 atm_tree = proto_item_add_subtree(ti, ett_atm);
1174 switch (pinfo->pseudo_header->atm.channel) {
1177 /* Traffic from DTE to DCE. */
1178 proto_tree_add_text(atm_tree, tvb, 0, 0, "Channel: DTE->DCE");
1182 /* Traffic from DCE to DTE. */
1183 proto_tree_add_text(atm_tree, tvb, 0, 0, "Channel: DCE->DTE");
1187 /* Sniffers shouldn't provide anything other than 0 or 1. */
1188 proto_tree_add_text(atm_tree, tvb, 0, 0, "Channel: %u",
1189 pinfo->pseudo_header->atm.channel);
1193 proto_tree_add_uint_format(atm_tree, hf_atm_aal, tvb, 0, 0,
1194 pinfo->pseudo_header->atm.aal,
1196 val_to_str(pinfo->pseudo_header->atm.aal, aal_vals,
1197 "Unknown AAL (%u)"));
1199 if (pinfo->pseudo_header->atm.aal == AAL_5 ||
1200 pinfo->pseudo_header->atm.aal == AAL_SIGNALLING) {
1201 /* This is a reassembled PDU. */
1202 dissect_reassembled_pdu(tvb, pinfo, tree, atm_tree, truncated);
1204 /* Assume this is a single cell, with the cell header at the beginning. */
1205 proto_item_set_len(ti, 5);
1206 dissect_atm_cell(tvb, pinfo, tree, atm_tree);
1211 dissect_atm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1213 dissect_atm_common(tvb, pinfo, tree, TRUE);
1217 dissect_atm_untruncated(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1219 dissect_atm_common(tvb, pinfo, tree, FALSE);
1223 proto_register_atm(void)
1225 static hf_register_info hf[] = {
1227 { "AAL", "atm.aal", FT_UINT8, BASE_DEC, VALS(aal_vals), 0x0,
1231 { "VPI", "atm.vpi", FT_UINT8, BASE_DEC, NULL, 0x0,
1235 { "VCI", "atm.vci", FT_UINT16, BASE_DEC, NULL, 0x0,
1238 static gint *ett[] = {
1245 &ett_atm_lane_lc_lan_dest,
1246 &ett_atm_lane_lc_lan_dest_rd,
1247 &ett_atm_lane_lc_flags,
1248 &ett_atm_lane_lc_tlv,
1250 proto_atm = proto_register_protocol("ATM", "ATM", "atm");
1251 proto_aal1 = proto_register_protocol("ATM AAL1", "AAL1", "aal1");
1252 proto_aal3_4 = proto_register_protocol("ATM AAL3/4", "AAL3_4", "aal3_4");
1253 proto_oamaal = proto_register_protocol("ATM OAM AAL", "OAM AAL", "oamaal");
1254 proto_register_field_array(proto_atm, hf, array_length(hf));
1255 proto_register_subtree_array(ett, array_length(ett));
1257 proto_ilmi = proto_register_protocol("ILMI", "ILMI", "ilmi");
1259 register_dissector("ilmi", dissect_ilmi, proto_ilmi);
1261 proto_atm_lane = proto_register_protocol("ATM LAN Emulation",
1262 "ATM LANE", "lane");
1264 register_dissector("lane", dissect_lane, proto_atm_lane);
1268 proto_reg_handoff_atm(void)
1270 dissector_handle_t atm_handle, atm_untruncated_handle;
1273 * Get handles for the Ethernet, Token Ring, LLC, SSCOP, LANE,
1274 * and ILMI dissectors.
1276 eth_handle = find_dissector("eth");
1277 tr_handle = find_dissector("tr");
1278 llc_handle = find_dissector("llc");
1279 sscop_handle = find_dissector("sscop");
1280 lane_handle = find_dissector("lane");
1281 ilmi_handle = find_dissector("ilmi");
1282 data_handle = find_dissector("data");
1284 atm_handle = create_dissector_handle(dissect_atm, proto_atm);
1285 dissector_add("wtap_encap", WTAP_ENCAP_ATM_PDUS, atm_handle);
1287 atm_untruncated_handle = create_dissector_handle(dissect_atm_untruncated,
1289 dissector_add("wtap_encap", WTAP_ENCAP_ATM_PDUS_UNTRUNCATED,
1290 atm_untruncated_handle);