2 * Routines for ATM packet disassembly
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31 #include <epan/packet.h>
33 #include <epan/addr_resolv.h>
34 #include <epan/ppptypes.h>
36 #include "packet-atm.h"
37 #include "packet-snmp.h"
38 #include "packet-eth.h"
39 #include "packet-tr.h"
40 #include "packet-llc.h"
42 #include "packet-pw-atm.h"
44 static int proto_atm = -1;
45 static int hf_atm_aal = -1;
46 static int hf_atm_vpi = -1;
47 static int hf_atm_vci = -1;
48 static int hf_atm_cid = -1;
49 static int proto_atm_lane = -1;
50 static int proto_ilmi = -1;
51 static int proto_aal1 = -1;
52 static int proto_aal3_4 = -1;
53 static int proto_oamaal = -1;
55 static gint ett_atm = -1;
56 static gint ett_atm_lane = -1;
57 static gint ett_atm_lane_lc_lan_dest = -1;
58 static gint ett_atm_lane_lc_lan_dest_rd = -1;
59 static gint ett_atm_lane_lc_flags = -1;
60 static gint ett_atm_lane_lc_tlv = -1;
61 static gint ett_ilmi = -1;
62 static gint ett_aal1 = -1;
63 static gint ett_aal3_4 = -1;
64 static gint ett_oamaal = -1;
66 static dissector_handle_t eth_withoutfcs_handle;
67 static dissector_handle_t tr_handle;
68 static dissector_handle_t fr_handle;
69 static dissector_handle_t llc_handle;
70 static dissector_handle_t sscop_handle;
71 static dissector_handle_t lane_handle;
72 static dissector_handle_t ilmi_handle;
73 static dissector_handle_t fp_handle;
74 static dissector_handle_t ppp_handle;
75 static dissector_handle_t eth_handle;
76 static dissector_handle_t ip_handle;
77 static dissector_handle_t data_handle;
79 static gboolean dissect_lanesscop = FALSE;
84 * http://www.atmforum.org/atmforum/specs/approved.html
86 * for a number of ATM Forum specifications, e.g. the LAN Emulation
87 * over ATM 1.0 spec, whence I got most of this.
90 /* LE Control opcodes */
91 #define LE_CONFIGURE_REQUEST 0x0001
92 #define LE_CONFIGURE_RESPONSE 0x0101
93 #define LE_JOIN_REQUEST 0x0002
94 #define LE_JOIN_RESPONSE 0x0102
95 #define READY_QUERY 0x0003
96 #define READY_IND 0x0103
97 #define LE_REGISTER_REQUEST 0x0004
98 #define LE_REGISTER_RESPONSE 0x0104
99 #define LE_UNREGISTER_REQUEST 0x0005
100 #define LE_UNREGISTER_RESPONSE 0x0105
101 #define LE_ARP_REQUEST 0x0006
102 #define LE_ARP_RESPONSE 0x0106
103 #define LE_FLUSH_REQUEST 0x0007
104 #define LE_FLUSH_RESPONSE 0x0107
105 #define LE_NARP_REQUEST 0x0008
106 #define LE_TOPOLOGY_REQUEST 0x0009
107 #define LE_VERIFY_REQUEST 0x000A
108 #define LE_VERIFY_RESPONSE 0x010A
110 static const value_string le_control_opcode_vals[] = {
111 { LE_CONFIGURE_REQUEST, "LE_CONFIGURE_REQUEST" },
112 { LE_CONFIGURE_RESPONSE, "LE_CONFIGURE_RESPONSE" },
113 { LE_JOIN_REQUEST, "LE_JOIN_REQUEST" },
114 { LE_JOIN_RESPONSE, "LE_JOIN_RESPONSE" },
115 { READY_QUERY, "READY_QUERY" },
116 { READY_IND, "READY_IND" },
117 { LE_REGISTER_REQUEST, "LE_REGISTER_REQUEST" },
118 { LE_REGISTER_RESPONSE, "LE_REGISTER_RESPONSE" },
119 { LE_UNREGISTER_REQUEST, "LE_UNREGISTER_REQUEST" },
120 { LE_UNREGISTER_RESPONSE, "LE_UNREGISTER_RESPONSE" },
121 { LE_ARP_REQUEST, "LE_ARP_REQUEST" },
122 { LE_ARP_RESPONSE, "LE_ARP_RESPONSE" },
123 { LE_FLUSH_REQUEST, "LE_FLUSH_REQUEST" },
124 { LE_FLUSH_RESPONSE, "LE_FLUSH_RESPONSE" },
125 { LE_NARP_REQUEST, "LE_NARP_REQUEST" },
126 { LE_TOPOLOGY_REQUEST, "LE_TOPOLOGY_REQUEST" },
127 { LE_VERIFY_REQUEST, "LE_VERIFY_REQUEST" },
128 { LE_VERIFY_RESPONSE, "LE_VERIFY_RESPONSE" },
132 /* LE Control statuses */
133 static const value_string le_control_status_vals[] = {
135 { 1, "Version not supported" },
136 { 2, "Invalid request parameters" },
137 { 4, "Duplicate LAN destination registration" },
138 { 5, "Duplicate ATM address" },
139 { 6, "Insufficient resources to grant request" },
140 { 7, "Access denied" },
141 { 8, "Invalid REQUESTOR-ID" },
142 { 9, "Invalid LAN destination" },
143 { 10, "Invalid ATM address" },
144 { 20, "No configuration" },
145 { 21, "LE_CONFIGURE error" },
146 { 22, "Insufficient information" },
147 { 24, "TLV not found" },
151 /* LE Control LAN destination tags */
152 #define TAG_NOT_PRESENT 0x0000
153 #define TAG_MAC_ADDRESS 0x0001
154 #define TAG_ROUTE_DESCRIPTOR 0x0002
156 static const value_string le_control_landest_tag_vals[] = {
157 { TAG_NOT_PRESENT, "Not present" },
158 { TAG_MAC_ADDRESS, "MAC address" },
159 { TAG_ROUTE_DESCRIPTOR, "Route descriptor" },
163 /* LE Control LAN types */
164 #define LANT_UNSPEC 0x00
165 #define LANT_802_3 0x01
166 #define LANT_802_5 0x02
168 static const value_string le_control_lan_type_vals[] = {
169 { LANT_UNSPEC, "Unspecified" },
170 { LANT_802_3, "Ethernet/802.3" },
171 { LANT_802_5, "802.5" },
175 static const value_string le_control_frame_size_vals[] = {
176 { 0x00, "Unspecified" },
177 { 0x01, "1516/1528/1580/1592" },
178 { 0x02, "4544/4556/1580/1592" },
179 { 0x03, "9234/9246" },
180 { 0x04, "18190/18202" },
185 dissect_le_client(tvbuff_t *tvb, proto_tree *tree)
188 proto_tree *lane_tree;
191 ti = proto_tree_add_protocol_format(tree, proto_atm_lane, tvb, 0, 2, "ATM LANE");
192 lane_tree = proto_item_add_subtree(ti, ett_atm_lane);
194 proto_tree_add_text(lane_tree, tvb, 0, 2, "LE Client: 0x%04X",
195 tvb_get_ntohs(tvb, 0));
200 dissect_lan_destination(tvbuff_t *tvb, int offset, const char *type, proto_tree *tree)
203 proto_tree *dest_tree;
207 guint16 route_descriptor;
209 td = proto_tree_add_text(tree, tvb, offset, 8, "%s LAN destination",
211 dest_tree = proto_item_add_subtree(td, ett_atm_lane_lc_lan_dest);
212 tag = tvb_get_ntohs(tvb, offset);
213 proto_tree_add_text(dest_tree, tvb, offset, 2, "Tag: %s",
214 val_to_str(tag, le_control_landest_tag_vals,
215 "Unknown (0x%04X)"));
220 case TAG_MAC_ADDRESS:
221 proto_tree_add_text(dest_tree, tvb, offset, 6, "MAC address: %s",
222 ether_to_str(tvb_get_ptr(tvb, offset, 6)));
225 case TAG_ROUTE_DESCRIPTOR:
227 route_descriptor = tvb_get_ntohs(tvb, offset);
228 trd = proto_tree_add_text(dest_tree, tvb, offset, 2, "Route descriptor: 0x%02X",
230 rd_tree = proto_item_add_subtree(td, ett_atm_lane_lc_lan_dest_rd);
231 proto_tree_add_text(rd_tree, tvb, offset, 2, "%s",
232 decode_numeric_bitfield(route_descriptor, 0xFFF0, 2*8,
234 proto_tree_add_text(rd_tree, tvb, offset, 2, "%s",
235 decode_numeric_bitfield(route_descriptor, 0x000F, 2*8,
236 "Bridge number = %u"));
242 * TLV values in LE Control frames.
244 #define TLV_TYPE(oui, ident) (((oui) << 8) | (ident))
246 #define LE_CONTROL_TIMEOUT TLV_TYPE(OUI_ATM_FORUM, 0x01)
247 #define LE_MAX_UNK_FRAME_COUNT TLV_TYPE(OUI_ATM_FORUM, 0x02)
248 #define LE_MAX_UNK_FRAME_TIME TLV_TYPE(OUI_ATM_FORUM, 0x03)
249 #define LE_VCC_TIMEOUT_PERIOD TLV_TYPE(OUI_ATM_FORUM, 0x04)
250 #define LE_MAX_RETRY_COUNT TLV_TYPE(OUI_ATM_FORUM, 0x05)
251 #define LE_AGING_TIME TLV_TYPE(OUI_ATM_FORUM, 0x06)
252 #define LE_FORWARD_DELAY_TIME TLV_TYPE(OUI_ATM_FORUM, 0x07)
253 #define LE_EXPECTED_ARP_RESPONSE_TIME TLV_TYPE(OUI_ATM_FORUM, 0x08)
254 #define LE_FLUSH_TIMEOUT TLV_TYPE(OUI_ATM_FORUM, 0x09)
255 #define LE_PATH_SWITCHING_DELAY TLV_TYPE(OUI_ATM_FORUM, 0x0A)
256 #define LE_LOCAL_SEGMENT_ID TLV_TYPE(OUI_ATM_FORUM, 0x0B)
257 #define LE_MCAST_SEND_VCC_TYPE TLV_TYPE(OUI_ATM_FORUM, 0x0C)
258 #define LE_MCAST_SEND_VCC_AVGRATE TLV_TYPE(OUI_ATM_FORUM, 0x0D)
259 #define LE_MCAST_SEND_VCC_PEAKRATE TLV_TYPE(OUI_ATM_FORUM, 0x0E)
260 #define LE_CONN_COMPLETION_TIMER TLV_TYPE(OUI_ATM_FORUM, 0x0F)
261 #define LE_CONFIG_FRAG_INFO TLV_TYPE(OUI_ATM_FORUM, 0x10)
262 #define LE_LAYER_3_ADDRESS TLV_TYPE(OUI_ATM_FORUM, 0x11)
263 #define LE_ELAN_ID TLV_TYPE(OUI_ATM_FORUM, 0x12)
264 #define LE_SERVICE_CATEGORY TLV_TYPE(OUI_ATM_FORUM, 0x13)
265 #define LE_LLC_MUXED_ATM_ADDRESS TLV_TYPE(OUI_ATM_FORUM, 0x2B)
266 #define LE_X5_ADJUSTMENT TLV_TYPE(OUI_ATM_FORUM, 0x2C)
267 #define LE_PREFERRED_LES TLV_TYPE(OUI_ATM_FORUM, 0x2D)
269 static const value_string le_tlv_type_vals[] = {
270 { LE_CONTROL_TIMEOUT, "Control Time-out" },
271 { LE_MAX_UNK_FRAME_COUNT, "Maximum Unknown Frame Count" },
272 { LE_MAX_UNK_FRAME_TIME, "Maximum Unknown Frame Time" },
273 { LE_VCC_TIMEOUT_PERIOD, "VCC Time-out" },
274 { LE_MAX_RETRY_COUNT, "Maximum Retry Count" },
275 { LE_AGING_TIME, "Aging Time" },
276 { LE_FORWARD_DELAY_TIME, "Forwarding Delay Time" },
277 { LE_EXPECTED_ARP_RESPONSE_TIME, "Expected LE_ARP Response Time" },
278 { LE_FLUSH_TIMEOUT, "Flush Time-out" },
279 { LE_PATH_SWITCHING_DELAY, "Path Switching Delay" },
280 { LE_LOCAL_SEGMENT_ID, "Local Segment ID" },
281 { LE_MCAST_SEND_VCC_TYPE, "Mcast Send VCC Type" },
282 { LE_MCAST_SEND_VCC_AVGRATE, "Mcast Send VCC AvgRate" },
283 { LE_MCAST_SEND_VCC_PEAKRATE, "Mcast Send VCC PeakRate" },
284 { LE_CONN_COMPLETION_TIMER, "Connection Completion Timer" },
285 { LE_CONFIG_FRAG_INFO, "Config Frag Info" },
286 { LE_LAYER_3_ADDRESS, "Layer 3 Address" },
287 { LE_ELAN_ID, "ELAN ID" },
288 { LE_SERVICE_CATEGORY, "Service Category" },
289 { LE_LLC_MUXED_ATM_ADDRESS, "LLC-muxed ATM Address" },
290 { LE_X5_ADJUSTMENT, "X5 Adjustment" },
291 { LE_PREFERRED_LES, "Preferred LES" },
296 dissect_le_control_tlvs(tvbuff_t *tvb, int offset, guint num_tlvs,
302 proto_tree *tlv_tree;
304 while (num_tlvs != 0) {
305 tlv_type = tvb_get_ntohl(tvb, offset);
306 tlv_length = tvb_get_guint8(tvb, offset+4);
307 ttlv = proto_tree_add_text(tree, tvb, offset, 5+tlv_length, "TLV type: %s",
308 val_to_str(tlv_type, le_tlv_type_vals, "Unknown (0x%08x)"));
309 tlv_tree = proto_item_add_subtree(ttlv, ett_atm_lane_lc_tlv);
310 proto_tree_add_text(tlv_tree, tvb, offset, 4, "TLV Type: %s",
311 val_to_str(tlv_type, le_tlv_type_vals, "Unknown (0x%08x)"));
312 proto_tree_add_text(tlv_tree, tvb, offset+4, 1, "TLV Length: %u", tlv_length);
313 offset += 5+tlv_length;
319 dissect_le_configure_join_frame(tvbuff_t *tvb, int offset, proto_tree *tree)
324 dissect_lan_destination(tvb, offset, "Source", tree);
327 dissect_lan_destination(tvb, offset, "Target", tree);
330 proto_tree_add_text(tree, tvb, offset, 20, "Source ATM Address: %s",
331 tvb_bytes_to_str(tvb, offset, 20));
334 proto_tree_add_text(tree, tvb, offset, 1, "LAN type: %s",
335 val_to_str(tvb_get_guint8(tvb, offset), le_control_lan_type_vals,
336 "Unknown (0x%02X)"));
339 proto_tree_add_text(tree, tvb, offset, 1, "Maximum frame size: %s",
340 val_to_str(tvb_get_guint8(tvb, offset), le_control_frame_size_vals,
341 "Unknown (0x%02X)"));
344 num_tlvs = tvb_get_guint8(tvb, offset);
345 proto_tree_add_text(tree, tvb, offset, 1, "Number of TLVs: %u", num_tlvs);
348 name_size = tvb_get_guint8(tvb, offset);
349 proto_tree_add_text(tree, tvb, offset, 1, "ELAN name size: %u", name_size);
352 proto_tree_add_text(tree, tvb, offset, 20, "Target ATM Address: %s",
353 tvb_bytes_to_str(tvb, offset, 20));
358 if (name_size != 0) {
359 proto_tree_add_text(tree, tvb, offset, name_size, "ELAN name: %s",
360 tvb_bytes_to_str(tvb, offset, name_size));
364 dissect_le_control_tlvs(tvb, offset, num_tlvs, tree);
368 dissect_le_registration_frame(tvbuff_t *tvb, int offset, proto_tree *tree)
372 dissect_lan_destination(tvb, offset, "Source", tree);
375 dissect_lan_destination(tvb, offset, "Target", tree);
378 proto_tree_add_text(tree, tvb, offset, 20, "Source ATM Address: %s",
379 tvb_bytes_to_str(tvb, offset, 20));
385 num_tlvs = tvb_get_guint8(tvb, offset);
386 proto_tree_add_text(tree, tvb, offset, 1, "Number of TLVs: %u", num_tlvs);
392 dissect_le_control_tlvs(tvb, offset, num_tlvs, tree);
396 dissect_le_arp_frame(tvbuff_t *tvb, int offset, proto_tree *tree)
400 dissect_lan_destination(tvb, offset, "Source", tree);
403 dissect_lan_destination(tvb, offset, "Target", tree);
406 proto_tree_add_text(tree, tvb, offset, 20, "Source ATM Address: %s",
407 tvb_bytes_to_str(tvb, offset, 20));
413 num_tlvs = tvb_get_guint8(tvb, offset);
414 proto_tree_add_text(tree, tvb, offset, 1, "Number of TLVs: %u", num_tlvs);
420 proto_tree_add_text(tree, tvb, offset, 20, "Target ATM Address: %s",
421 tvb_bytes_to_str(tvb, offset, 20));
427 dissect_le_control_tlvs(tvb, offset, num_tlvs, tree);
431 dissect_le_verify_frame(tvbuff_t *tvb, int offset, proto_tree *tree)
438 num_tlvs = tvb_get_guint8(tvb, offset);
439 proto_tree_add_text(tree, tvb, offset, 1, "Number of TLVs: %u", num_tlvs);
445 proto_tree_add_text(tree, tvb, offset, 20, "Target ATM Address: %s",
446 tvb_bytes_to_str(tvb, offset, 20));
452 dissect_le_control_tlvs(tvb, offset, num_tlvs, tree);
456 dissect_le_flush_frame(tvbuff_t *tvb, int offset, proto_tree *tree)
458 dissect_lan_destination(tvb, offset, "Source", tree);
461 dissect_lan_destination(tvb, offset, "Target", tree);
464 proto_tree_add_text(tree, tvb, offset, 20, "Source ATM Address: %s",
465 tvb_bytes_to_str(tvb, offset, 20));
471 proto_tree_add_text(tree, tvb, offset, 20, "Target ATM Address: %s",
472 tvb_bytes_to_str(tvb, offset, 20));
480 dissect_le_control(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
483 proto_tree *lane_tree = NULL;
486 proto_tree *flags_tree;
490 if (check_col(pinfo->cinfo, COL_INFO))
491 col_set_str(pinfo->cinfo, COL_INFO, "LE Control");
494 ti = proto_tree_add_protocol_format(tree, proto_atm_lane, tvb, offset, 108, "ATM LANE");
495 lane_tree = proto_item_add_subtree(ti, ett_atm_lane);
497 proto_tree_add_text(lane_tree, tvb, offset, 2, "Marker: 0x%04X",
498 tvb_get_ntohs(tvb, offset));
503 proto_tree_add_text(lane_tree, tvb, offset, 1, "Protocol: 0x%02X",
504 tvb_get_guint8(tvb, offset));
509 proto_tree_add_text(lane_tree, tvb, offset, 1, "Version: 0x%02X",
510 tvb_get_guint8(tvb, offset));
514 opcode = tvb_get_ntohs(tvb, offset);
515 if (check_col(pinfo->cinfo, COL_INFO)) {
516 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s",
517 val_to_str(opcode, le_control_opcode_vals,
518 "Unknown opcode (0x%04X)"));
521 proto_tree_add_text(lane_tree, tvb, offset, 2, "Opcode: %s",
522 val_to_str(opcode, le_control_opcode_vals,
523 "Unknown (0x%04X)"));
527 if (opcode == READY_QUERY || opcode == READY_IND) {
528 /* There's nothing more in this packet. */
533 if (opcode & 0x0100) {
534 /* Response; decode status. */
535 proto_tree_add_text(lane_tree, tvb, offset, 2, "Status: %s",
536 val_to_str(tvb_get_ntohs(tvb, offset), le_control_status_vals,
537 "Unknown (0x%04X)"));
541 proto_tree_add_text(lane_tree, tvb, offset, 4, "Transaction ID: 0x%08X",
542 tvb_get_ntohl(tvb, offset));
545 proto_tree_add_text(lane_tree, tvb, offset, 2, "Requester LECID: 0x%04X",
546 tvb_get_ntohs(tvb, offset));
549 flags = tvb_get_ntohs(tvb, offset);
550 tf = proto_tree_add_text(lane_tree, tvb, offset, 2, "Flags: 0x%04X",
552 flags_tree = proto_item_add_subtree(tf, ett_atm_lane_lc_flags);
556 case LE_CONFIGURE_REQUEST:
557 case LE_CONFIGURE_RESPONSE:
558 proto_tree_add_text(flags_tree, tvb, offset, 2, "%s",
559 decode_boolean_bitfield(flags, 0x0002, 8*2,
560 "V2 capable", "Not V2 capable"));
562 dissect_le_configure_join_frame(tvb, offset, lane_tree);
565 case LE_JOIN_REQUEST:
566 case LE_JOIN_RESPONSE:
567 proto_tree_add_text(flags_tree, tvb, offset, 2, "%s",
568 decode_boolean_bitfield(flags, 0x0002, 8*2,
569 "V2 capable", "Not V2 capable"));
570 if (opcode == LE_JOIN_REQUEST) {
571 proto_tree_add_text(flags_tree, tvb, offset, 2, "%s",
572 decode_boolean_bitfield(flags, 0x0004, 8*2,
573 "Selective multicast", "No selective multicast"));
575 proto_tree_add_text(flags_tree, tvb, offset, 2, "%s",
576 decode_boolean_bitfield(flags, 0x0008, 8*2,
577 "V2 required", "V2 not required"));
579 proto_tree_add_text(flags_tree, tvb, offset, 2, "%s",
580 decode_boolean_bitfield(flags, 0x0080, 8*2,
581 "Proxy", "Not proxy"));
582 proto_tree_add_text(flags_tree, tvb, offset, 2, "%s",
583 decode_boolean_bitfield(flags, 0x0200, 8*2,
584 "Exclude explorer frames",
585 "Don't exclude explorer frames"));
587 dissect_le_configure_join_frame(tvb, offset, lane_tree);
590 case LE_REGISTER_REQUEST:
591 case LE_REGISTER_RESPONSE:
592 case LE_UNREGISTER_REQUEST:
593 case LE_UNREGISTER_RESPONSE:
595 dissect_le_registration_frame(tvb, offset, lane_tree);
599 case LE_ARP_RESPONSE:
600 case LE_NARP_REQUEST:
601 if (opcode != LE_NARP_REQUEST) {
602 proto_tree_add_text(flags_tree, tvb, offset, 2, "%s",
603 decode_boolean_bitfield(flags, 0x0001, 8*2,
604 "Remote address", "Local address"));
607 dissect_le_arp_frame(tvb, offset, lane_tree);
610 case LE_TOPOLOGY_REQUEST:
611 proto_tree_add_text(flags_tree, tvb, offset, 2, "%s",
612 decode_boolean_bitfield(flags, 0x0100, 8*2,
613 "Topology change", "No topology change"));
615 /* 92 reserved bytes */
618 case LE_VERIFY_REQUEST:
619 case LE_VERIFY_RESPONSE:
621 dissect_le_verify_frame(tvb, offset, lane_tree);
624 case LE_FLUSH_REQUEST:
625 case LE_FLUSH_RESPONSE:
627 dissect_le_flush_frame(tvb, offset, lane_tree);
634 capture_lane(const union wtap_pseudo_header *pseudo_header, const guchar *pd,
635 int len, packet_counts *ld)
637 /* Is it LE Control, 802.3, 802.5, or "none of the above"? */
638 switch (pseudo_header->atm.subtype) {
640 case TRAF_ST_LANE_802_3:
641 case TRAF_ST_LANE_802_3_MC:
642 /* Dissect as Ethernet */
643 capture_eth(pd, 2, len, ld);
646 case TRAF_ST_LANE_802_5:
647 case TRAF_ST_LANE_802_5_MC:
648 /* Dissect as Token-Ring */
649 capture_tr(pd, 2, len, ld);
659 dissect_lane(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
662 tvbuff_t *next_tvb_le_client;
664 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATM LANE");
666 /* Is it LE Control, 802.3, 802.5, or "none of the above"? */
667 switch (pinfo->pseudo_header->atm.subtype) {
669 case TRAF_ST_LANE_LE_CTRL:
670 dissect_le_control(tvb, pinfo, tree);
673 case TRAF_ST_LANE_802_3:
674 case TRAF_ST_LANE_802_3_MC:
675 if (check_col(pinfo->cinfo, COL_INFO))
676 col_set_str(pinfo->cinfo, COL_INFO, "LE Client - Ethernet/802.3");
677 dissect_le_client(tvb, tree);
679 /* Dissect as Ethernet */
680 next_tvb_le_client = tvb_new_subset(tvb, 2, -1, -1);
681 call_dissector(eth_withoutfcs_handle, next_tvb_le_client, pinfo, tree);
684 case TRAF_ST_LANE_802_5:
685 case TRAF_ST_LANE_802_5_MC:
686 if (check_col(pinfo->cinfo, COL_INFO))
687 col_set_str(pinfo->cinfo, COL_INFO, "LE Client - 802.5");
688 dissect_le_client(tvb, tree);
690 /* Dissect as Token-Ring */
691 next_tvb_le_client = tvb_new_subset(tvb, 2, -1, -1);
692 call_dissector(tr_handle, next_tvb_le_client, pinfo, tree);
696 /* Dump it as raw data. */
697 if (check_col(pinfo->cinfo, COL_INFO))
698 col_set_str(pinfo->cinfo, COL_INFO, "Unknown LANE traffic type");
699 next_tvb = tvb_new_subset(tvb, 0, -1, -1);
700 call_dissector(data_handle,next_tvb, pinfo, tree);
706 dissect_ilmi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
708 dissect_snmp_pdu(tvb, 0, pinfo, tree, proto_ilmi, ett_ilmi, FALSE);
712 static const value_string aal_vals[] = {
713 { AAL_UNKNOWN, "Unknown AAL" },
716 { AAL_3_4, "AAL3/4" },
718 { AAL_USER, "User AAL" },
719 { AAL_SIGNALLING, "Signalling AAL" },
720 { AAL_OAMCELL, "OAM cell" },
724 /* AAL5 higher-level traffic types */
725 static const value_string aal5_hltype_vals[] = {
726 { TRAF_UNKNOWN, "Unknown traffic type" },
727 { TRAF_LLCMX, "LLC multiplexed" },
728 { TRAF_VCMX, "VC multiplexed" },
729 { TRAF_LANE, "LANE" },
730 { TRAF_ILMI, "ILMI" },
731 { TRAF_FR, "Frame Relay" },
732 { TRAF_SPANS, "FORE SPANS" },
733 { TRAF_IPSILON, "Ipsilon" },
737 /* Traffic subtypes for VC multiplexed traffic */
738 static const value_string vcmx_type_vals[] = {
739 { TRAF_ST_UNKNOWN, "Unknown VC multiplexed traffic type" },
740 { TRAF_ST_VCMX_802_3_FCS, "802.3 FCS" },
741 { TRAF_ST_VCMX_802_4_FCS, "802.4 FCS" },
742 { TRAF_ST_VCMX_802_5_FCS, "802.5 FCS" },
743 { TRAF_ST_VCMX_FDDI_FCS, "FDDI FCS" },
744 { TRAF_ST_VCMX_802_6_FCS, "802.6 FCS" },
745 { TRAF_ST_VCMX_802_3, "802.3" },
746 { TRAF_ST_VCMX_802_4, "802.4" },
747 { TRAF_ST_VCMX_802_5, "802.5" },
748 { TRAF_ST_VCMX_FDDI, "FDDI" },
749 { TRAF_ST_VCMX_802_6, "802.6" },
750 { TRAF_ST_VCMX_FRAGMENTS, "Fragments" },
751 { TRAF_ST_VCMX_BPDU, "BPDU" },
755 /* Traffic subtypes for LANE traffic */
756 static const value_string lane_type_vals[] = {
757 { TRAF_ST_UNKNOWN, "Unknown LANE traffic type" },
758 { TRAF_ST_LANE_LE_CTRL, "LE Control" },
759 { TRAF_ST_LANE_802_3, "802.3" },
760 { TRAF_ST_LANE_802_5, "802.5" },
761 { TRAF_ST_LANE_802_3_MC, "802.3 multicast" },
762 { TRAF_ST_LANE_802_5_MC, "802.5 multicast" },
766 /* Traffic subtypes for Ipsilon traffic */
767 static const value_string ipsilon_type_vals[] = {
768 { TRAF_ST_UNKNOWN, "Unknown Ipsilon traffic type" },
769 { TRAF_ST_IPSILON_FT0, "Flow type 0" },
770 { TRAF_ST_IPSILON_FT1, "Flow type 1" },
771 { TRAF_ST_IPSILON_FT2, "Flow type 2" },
776 capture_atm(const union wtap_pseudo_header *pseudo_header, const guchar *pd,
777 int len, packet_counts *ld)
779 if (pseudo_header->atm.aal == AAL_5) {
780 switch (pseudo_header->atm.type) {
783 /* Dissect as WTAP_ENCAP_ATM_RFC1483 */
784 /* The ATM iptrace capture that we have shows LLC at this point,
785 * so that's what I'm calling */
786 capture_llc(pd, 0, len, ld);
790 capture_lane(pseudo_header, pd, len, ld);
802 * Charles Michael Heard's CRC-32 code, from
804 * http://www.cell-relay.com/cell-relay/publications/software/CRC/32bitCRC.c.html
806 * with the CRC table initialized with values computed by
807 * his "gen_crc_table()" routine, rather than by calling that routine
808 * at run time, and with various data type cleanups.
811 /* crc32h.c -- package to compute 32-bit CRC one byte at a time using */
812 /* the high-bit first (Big-Endian) bit ordering convention */
815 /* gen_crc_table() -- generates a 256-word table containing all CRC */
816 /* remainders for every possible 8-bit byte. It */
817 /* must be executed (once) before any CRC updates. */
819 /* unsigned update_crc(crc_accum, data_blk_ptr, data_blk_size) */
820 /* unsigned crc_accum; char *data_blk_ptr; int data_blk_size; */
821 /* Returns the updated value of the CRC accumulator after */
822 /* processing each byte in the addressed block of data. */
824 /* It is assumed that an unsigned long is at least 32 bits wide and */
825 /* that the predefined type char occupies one 8-bit byte of storage. */
827 /* The generator polynomial used for this version of the package is */
828 /* 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 */
829 /* as specified in the Autodin/Ethernet/ADCCP protocol standards. */
830 /* Other degree 32 polynomials may be substituted by re-defining the */
831 /* symbol POLYNOMIAL below. Lower degree polynomials must first be */
832 /* multiplied by an appropriate power of x. The representation used */
833 /* is that the coefficient of x^0 is stored in the LSB of the 32-bit */
834 /* word and the coefficient of x^31 is stored in the most significant */
835 /* bit. The CRC is to be appended to the data most significant byte */
836 /* first. For those protocols in which bytes are transmitted MSB */
837 /* first and in the same order as they are encountered in the block */
838 /* this convention results in the CRC remainder being transmitted with */
839 /* the coefficient of x^31 first and with that of x^0 last (just as */
840 /* would be done by a hardware shift register mechanization). */
842 /* The table lookup technique was adapted from the algorithm described */
843 /* by Avram Perez, Byte-wise CRC Calculations, IEEE Micro 3, 40 (1983).*/
845 static const guint32 crc_table[256] = {
846 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
847 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
848 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
849 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
850 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,
851 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
852 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011,
853 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
854 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
855 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
856 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,
857 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
858 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49,
859 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
860 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
861 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
862 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,
863 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
864 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
865 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
866 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
867 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
868 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,
869 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
870 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e,
871 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
872 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
873 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
874 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
875 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
876 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686,
877 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
878 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
879 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
880 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,
881 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
882 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47,
883 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
884 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
885 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
886 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,
887 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
888 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f,
889 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
890 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
891 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
892 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,
893 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
894 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
895 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
896 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
897 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
898 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
899 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
900 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,
901 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
902 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
903 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
904 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
905 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
906 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,
907 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
908 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
909 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4,
913 update_crc(guint32 crc_accum, const guint8 *data_blk_ptr, int data_blk_size)
917 /* update the CRC on the data block one byte at a time */
918 for (j = 0; j < data_blk_size; j++) {
919 i = ( (int) ( crc_accum >> 24) ^ *data_blk_ptr++ ) & 0xff;
920 crc_accum = ( crc_accum << 8 ) ^ crc_table[i];
926 dissect_reassembled_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
928 proto_tree *atm_tree, gboolean truncated)
930 guint length, reported_length;
937 * ATM dissector is used as "sub-dissector" for ATM pseudowires.
938 * In such cases, pinfo->private_data is used to pass info from/to
939 * PW dissector to ATM dissector. For decoding normal ATM traffic
940 * private_data should be NULL.
942 gboolean pseudowire_mode = (NULL != pinfo->private_data);
945 * This is reassembled traffic, so the cell headers are missing;
946 * show the traffic type for AAL5 traffic, and the VPI and VCI,
947 * from the pseudo-header.
949 if (pinfo->pseudo_header->atm.aal == AAL_5) {
950 proto_tree_add_text(atm_tree, tvb, 0, 0, "Traffic type: %s",
951 val_to_str(pinfo->pseudo_header->atm.type, aal5_hltype_vals,
952 "Unknown AAL5 traffic type (%u)"));
953 switch (pinfo->pseudo_header->atm.type) {
956 proto_tree_add_text(atm_tree, tvb, 0, 0, "VC multiplexed traffic type: %s",
957 val_to_str(pinfo->pseudo_header->atm.subtype,
958 vcmx_type_vals, "Unknown VCMX traffic type (%u)"));
962 proto_tree_add_text(atm_tree, tvb, 0, 0, "LANE traffic type: %s",
963 val_to_str(pinfo->pseudo_header->atm.subtype,
964 lane_type_vals, "Unknown LANE traffic type (%u)"));
968 proto_tree_add_text(atm_tree, tvb, 0, 0, "Ipsilon traffic type: %s",
969 val_to_str(pinfo->pseudo_header->atm.subtype,
970 ipsilon_type_vals, "Unknown Ipsilon traffic type (%u)"));
974 if (!pseudowire_mode) {
975 proto_tree_add_uint(atm_tree, hf_atm_vpi, tvb, 0, 0,
976 pinfo->pseudo_header->atm.vpi);
977 proto_tree_add_uint(atm_tree, hf_atm_vci, tvb, 0, 0,
978 pinfo->pseudo_header->atm.vci);
980 /* Also show vpi/vci in info column */
981 if (check_col(pinfo->cinfo, COL_INFO))
983 col_append_fstr(pinfo->cinfo, COL_INFO, " VPI=%u, VCI=%u",
984 pinfo->pseudo_header->atm.vpi,
985 pinfo->pseudo_header->atm.vci);
992 * The packet data does not include stuff such as the AAL5
995 if (pinfo->pseudo_header->atm.cells != 0) {
997 * If the cell count is 0, assume it means we don't know how
1000 * XXX - also assume it means we don't know what was in the AAL5
1001 * trailer. We may, however, find some capture program that can
1002 * give us the AAL5 trailer information but not the cell count,
1003 * in which case we need some other way of indicating whether we
1004 * have the AAL5 trailer information.
1007 proto_tree_add_text(atm_tree, tvb, 0, 0, "Cells: %u",
1008 pinfo->pseudo_header->atm.cells);
1009 proto_tree_add_text(atm_tree, tvb, 0, 0, "AAL5 UU: 0x%02x",
1010 pinfo->pseudo_header->atm.aal5t_u2u >> 8);
1011 proto_tree_add_text(atm_tree, tvb, 0, 0, "AAL5 CPI: 0x%02x",
1012 pinfo->pseudo_header->atm.aal5t_u2u & 0xFF);
1013 proto_tree_add_text(atm_tree, tvb, 0, 0, "AAL5 len: %u",
1014 pinfo->pseudo_header->atm.aal5t_len);
1015 proto_tree_add_text(atm_tree, tvb, 0, 0, "AAL5 CRC: 0x%08X",
1016 pinfo->pseudo_header->atm.aal5t_chksum);
1021 * The packet data includes stuff such as the AAL5 trailer, if
1022 * it wasn't cut off by the snapshot length.
1023 * Decode the trailer, if present, and then chop it off.
1025 length = tvb_length(tvb);
1026 reported_length = tvb_reported_length(tvb);
1027 if ((reported_length % 48) == 0) {
1029 * Reported length is a multiple of 48, so we can presumably
1030 * divide it by 48 to get the number of cells.
1032 proto_tree_add_text(atm_tree, tvb, 0, 0, "Cells: %u",
1033 reported_length/48);
1035 if ((pinfo->pseudo_header->atm.aal == AAL_5 ||
1036 pinfo->pseudo_header->atm.aal == AAL_SIGNALLING) &&
1037 length >= reported_length) {
1039 * XXX - what if the packet is truncated? Can that happen?
1040 * What if you capture with Windows Sniffer on an ATM link
1041 * and tell it not to save the entire packet? What happens
1044 aal5_length = tvb_get_ntohs(tvb, length - 6);
1047 * Check for sanity in the AAL5 length. It must be > 0
1048 * and must be less than the amount of space left after
1049 * we remove the trailer.
1051 * If it's not sane, assume we don't have a trailer.
1053 if (aal5_length > 0 && aal5_length <= length - 8) {
1055 * How much padding is there?
1057 pad_length = length - aal5_length - 8;
1060 * There is no reason for more than 47 bytes of padding.
1061 * The most padding you can have would be 7 bytes at the
1062 * end of the next-to-last cell (8 bytes after the end of
1063 * the data means you can fit the trailer in that cell),
1064 * plus 40 bytes in the last cell (with the last 8 bytes
1067 * If there's more than 47 bytes of padding, assume we don't
1070 if (pad_length <= 47) {
1072 if (pad_length > 0) {
1073 proto_tree_add_text(atm_tree, tvb, aal5_length, pad_length,
1076 proto_tree_add_text(atm_tree, tvb, length - 8, 1, "AAL5 UU: 0x%02x",
1077 tvb_get_guint8(tvb, length - 8));
1078 proto_tree_add_text(atm_tree, tvb, length - 7, 1, "AAL5 CPI: 0x%02x",
1079 tvb_get_guint8(tvb, length - 7));
1080 proto_tree_add_text(atm_tree, tvb, length - 6, 2, "AAL5 len: %u",
1082 crc = tvb_get_ntohl(tvb, length - 4);
1083 calc_crc = update_crc(0xFFFFFFFF, tvb_get_ptr(tvb, 0, length),
1085 proto_tree_add_text(atm_tree, tvb, length - 4, 4,
1086 "AAL5 CRC: 0x%08X (%s)", crc,
1087 (calc_crc == 0xC704DD7B) ? "correct" : "incorrect");
1089 next_tvb = tvb_new_subset(tvb, 0, aal5_length, aal5_length);
1095 switch (pinfo->pseudo_header->atm.aal) {
1097 case AAL_SIGNALLING:
1098 call_dissector(sscop_handle, next_tvb, pinfo, tree);
1102 switch (pinfo->pseudo_header->atm.type) {
1105 call_dissector(fr_handle, next_tvb, pinfo, tree);
1109 call_dissector(llc_handle, next_tvb, pinfo, tree);
1113 call_dissector(lane_handle, next_tvb, pinfo, tree);
1117 call_dissector(ilmi_handle, next_tvb, pinfo, tree);
1122 gboolean decoded = FALSE;
1124 if (tvb_length(next_tvb) > 7) /* sizeof(octet) */
1127 tvb_memcpy(next_tvb, octet, 0, sizeof(octet));
1130 if (octet[0] == 0xaa
1132 && octet[2] == 0x03) /* LLC SNAP as per RFC2684 */
1134 call_dissector(llc_handle, next_tvb, pinfo, tree);
1136 else if ((pntohs(octet) & 0xff) == PPP_IP)
1138 call_dissector(ppp_handle, next_tvb, pinfo, tree);
1140 else if (pntohs(octet) == 0x00)
1142 /* assume vc muxed bridged ethernet */
1143 proto_tree_add_text(tree, tvb, 0, 2, "Pad: 0x0000");
1144 next_tvb = tvb_new_subset(tvb, 2, -1, -1);
1145 call_dissector(eth_handle, next_tvb, pinfo, tree);
1147 else if (octet[2] == 0x03 && /* NLPID */
1148 ((octet[3] == 0xcc || /* IPv4 */
1149 octet[3] == 0x8e) || /* IPv6 */
1150 (octet[3] == 0x00 && /* Eth */
1151 octet[4] == 0x80))) /* Eth */
1153 /* assume network interworking with FR 2 byte header */
1154 call_dissector(fr_handle, next_tvb, pinfo, tree);
1156 else if (octet[4] == 0x03 && /* NLPID */
1157 ((octet[5] == 0xcc || /* IPv4 */
1158 octet[5] == 0x8e) || /* IPv6 */
1159 (octet[5] == 0x00 && /* Eth */
1160 octet[6] == 0x80))) /* Eth */
1162 /* assume network interworking with FR 4 byte header */
1163 call_dissector(fr_handle, next_tvb, pinfo, tree);
1165 else if (((octet[0] & 0xf0)== 0x40) ||
1166 ((octet[0] & 0xf0) == 0x60))
1168 call_dissector(ip_handle, next_tvb, pinfo, tree);
1176 if (tree && !decoded) {
1177 /* Dump it as raw data. */
1178 call_dissector(data_handle, next_tvb, pinfo, tree);
1186 switch (pinfo->pseudo_header->atm.type) {
1188 /* Skip first 4 bytes of message
1192 Ignoring for now... */
1193 proto_tree_add_uint(atm_tree, hf_atm_cid, tvb, 0, 0,
1194 pinfo->pseudo_header->atm.aal2_cid);
1195 proto_item_append_text(atm_ti, " (vpi=%u vci=%u cid=%u)",
1196 pinfo->pseudo_header->atm.vpi,
1197 pinfo->pseudo_header->atm.vci,
1198 pinfo->pseudo_header->atm.aal2_cid);
1200 next_tvb = tvb_new_subset(tvb, 4, -1, -1);
1201 call_dissector(fp_handle, next_tvb, pinfo, tree);
1206 /* Dump it as raw data. */
1207 call_dissector(data_handle, next_tvb, pinfo, tree);
1215 /* Dump it as raw data. */
1216 call_dissector(data_handle, next_tvb, pinfo, tree);
1223 * Charles Michael Heard's HEC code, from
1225 * http://www.cell-relay.com/cell-relay/publications/software/CRC/32bitCRC.tutorial.html
1227 * with the syndrome and error position tables initialized with values
1228 * computed by his "gen_syndrome_table()" and "gen_err_posn_table()" routines,
1229 * rather than by calling those routines at run time, and with various data
1230 * type cleanups and changes not to correct the header if a correctible
1231 * error was detected.
1233 #define COSET_LEADER 0x055 /* x^6 + x^4 + x^2 + 1 */
1235 static const guint8 syndrome_table[256] = {
1236 0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15,
1237 0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d,
1238 0x70, 0x77, 0x7e, 0x79, 0x6c, 0x6b, 0x62, 0x65,
1239 0x48, 0x4f, 0x46, 0x41, 0x54, 0x53, 0x5a, 0x5d,
1240 0xe0, 0xe7, 0xee, 0xe9, 0xfc, 0xfb, 0xf2, 0xf5,
1241 0xd8, 0xdf, 0xd6, 0xd1, 0xc4, 0xc3, 0xca, 0xcd,
1242 0x90, 0x97, 0x9e, 0x99, 0x8c, 0x8b, 0x82, 0x85,
1243 0xa8, 0xaf, 0xa6, 0xa1, 0xb4, 0xb3, 0xba, 0xbd,
1244 0xc7, 0xc0, 0xc9, 0xce, 0xdb, 0xdc, 0xd5, 0xd2,
1245 0xff, 0xf8, 0xf1, 0xf6, 0xe3, 0xe4, 0xed, 0xea,
1246 0xb7, 0xb0, 0xb9, 0xbe, 0xab, 0xac, 0xa5, 0xa2,
1247 0x8f, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9d, 0x9a,
1248 0x27, 0x20, 0x29, 0x2e, 0x3b, 0x3c, 0x35, 0x32,
1249 0x1f, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0d, 0x0a,
1250 0x57, 0x50, 0x59, 0x5e, 0x4b, 0x4c, 0x45, 0x42,
1251 0x6f, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7d, 0x7a,
1252 0x89, 0x8e, 0x87, 0x80, 0x95, 0x92, 0x9b, 0x9c,
1253 0xb1, 0xb6, 0xbf, 0xb8, 0xad, 0xaa, 0xa3, 0xa4,
1254 0xf9, 0xfe, 0xf7, 0xf0, 0xe5, 0xe2, 0xeb, 0xec,
1255 0xc1, 0xc6, 0xcf, 0xc8, 0xdd, 0xda, 0xd3, 0xd4,
1256 0x69, 0x6e, 0x67, 0x60, 0x75, 0x72, 0x7b, 0x7c,
1257 0x51, 0x56, 0x5f, 0x58, 0x4d, 0x4a, 0x43, 0x44,
1258 0x19, 0x1e, 0x17, 0x10, 0x05, 0x02, 0x0b, 0x0c,
1259 0x21, 0x26, 0x2f, 0x28, 0x3d, 0x3a, 0x33, 0x34,
1260 0x4e, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5c, 0x5b,
1261 0x76, 0x71, 0x78, 0x7f, 0x6a, 0x6d, 0x64, 0x63,
1262 0x3e, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2c, 0x2b,
1263 0x06, 0x01, 0x08, 0x0f, 0x1a, 0x1d, 0x14, 0x13,
1264 0xae, 0xa9, 0xa0, 0xa7, 0xb2, 0xb5, 0xbc, 0xbb,
1265 0x96, 0x91, 0x98, 0x9f, 0x8a, 0x8d, 0x84, 0x83,
1266 0xde, 0xd9, 0xd0, 0xd7, 0xc2, 0xc5, 0xcc, 0xcb,
1267 0xe6, 0xe1, 0xe8, 0xef, 0xfa, 0xfd, 0xf4, 0xf3,
1270 #define NO_ERROR_DETECTED -128
1271 #define UNCORRECTIBLE_ERROR 128
1273 static const int err_posn_table[256] = {
1274 NO_ERROR_DETECTED, 39,
1275 38, UNCORRECTIBLE_ERROR,
1276 37, UNCORRECTIBLE_ERROR,
1277 UNCORRECTIBLE_ERROR, 31,
1278 36, UNCORRECTIBLE_ERROR,
1279 UNCORRECTIBLE_ERROR, 8,
1280 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1281 30, UNCORRECTIBLE_ERROR,
1282 35, UNCORRECTIBLE_ERROR,
1283 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1284 UNCORRECTIBLE_ERROR, 23,
1285 7, UNCORRECTIBLE_ERROR,
1286 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1287 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1288 29, UNCORRECTIBLE_ERROR,
1289 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1290 34, UNCORRECTIBLE_ERROR,
1291 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1292 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1293 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1294 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1295 22, UNCORRECTIBLE_ERROR,
1296 6, UNCORRECTIBLE_ERROR,
1297 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1298 UNCORRECTIBLE_ERROR, 0,
1299 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1300 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1301 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1302 28, UNCORRECTIBLE_ERROR,
1303 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1304 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1305 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1306 33, UNCORRECTIBLE_ERROR,
1307 UNCORRECTIBLE_ERROR, 10,
1308 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1309 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1310 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1311 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1312 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1313 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1314 UNCORRECTIBLE_ERROR, 12,
1315 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1316 21, UNCORRECTIBLE_ERROR,
1317 UNCORRECTIBLE_ERROR, 19,
1318 5, UNCORRECTIBLE_ERROR,
1319 UNCORRECTIBLE_ERROR, 17,
1320 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1321 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1322 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1323 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1324 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1325 UNCORRECTIBLE_ERROR, 3,
1326 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1327 UNCORRECTIBLE_ERROR, 15,
1328 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1329 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1330 27, UNCORRECTIBLE_ERROR,
1331 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1332 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1333 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1334 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1335 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1336 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1337 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1338 32, UNCORRECTIBLE_ERROR,
1339 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1340 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1341 9, UNCORRECTIBLE_ERROR,
1342 UNCORRECTIBLE_ERROR, 24,
1343 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1344 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1345 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1346 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1347 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1348 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1349 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1350 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1351 UNCORRECTIBLE_ERROR, 1,
1352 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1353 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1354 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1355 11, UNCORRECTIBLE_ERROR,
1356 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1357 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1358 20, UNCORRECTIBLE_ERROR,
1359 UNCORRECTIBLE_ERROR, 13,
1360 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1361 18, UNCORRECTIBLE_ERROR,
1362 4, UNCORRECTIBLE_ERROR,
1363 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1364 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1365 16, UNCORRECTIBLE_ERROR,
1366 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1367 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1368 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1369 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1370 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1371 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1372 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1373 UNCORRECTIBLE_ERROR, 25,
1374 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1375 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1376 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1377 2, UNCORRECTIBLE_ERROR,
1378 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1379 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1380 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1381 14, UNCORRECTIBLE_ERROR,
1382 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1383 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1384 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1385 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1386 26, UNCORRECTIBLE_ERROR,
1387 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1388 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1389 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1390 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1391 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1392 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1393 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1394 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1395 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1396 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1397 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1398 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1399 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1400 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1401 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1405 * Return an indication of whether there was an error in the cell header
1406 * and, if so, where the error was, if it was correctable.
1409 get_header_err(const guint8 *cell_header)
1411 register guint8 syndrome;
1412 register int i, err_posn;
1415 for (i = 0; i < 4; i++)
1416 syndrome = syndrome_table[syndrome ^ cell_header[i]];
1417 syndrome ^= cell_header[4] ^ COSET_LEADER;
1419 err_posn = err_posn_table [syndrome];
1422 return NO_ERROR_DETECTED;
1423 else if (err_posn < 40)
1426 return UNCORRECTIBLE_ERROR;
1429 const value_string atm_pt_vals[] = {
1430 { 0, "User data cell, congestion not experienced, SDU-type = 0" },
1431 { 1, "User data cell, congestion not experienced, SDU-type = 1" },
1432 { 2, "User data cell, congestion experienced, SDU-type = 0" },
1433 { 3, "User data cell, congestion experienced, SDU-type = 1" },
1434 { 4, "Segment OAM F5 flow related cell" },
1435 { 5, "End-to-end OAM F5 flow related cell" },
1436 { 6, "VC resource management cell" },
1441 * Charles Michael Heard's CRC-10 code, from
1443 * http://www.cell-relay.com/cell-relay/publications/software/CRC/crc10.html
1445 * with the CRC table initialized with values computed by
1446 * his "gen_byte_crc10_table()" routine, rather than by calling that
1447 * routine at run time, and with various data type cleanups.
1449 static const guint16 byte_crc10_table[256] = {
1450 0x0000, 0x0233, 0x0255, 0x0066, 0x0299, 0x00aa, 0x00cc, 0x02ff,
1451 0x0301, 0x0132, 0x0154, 0x0367, 0x0198, 0x03ab, 0x03cd, 0x01fe,
1452 0x0031, 0x0202, 0x0264, 0x0057, 0x02a8, 0x009b, 0x00fd, 0x02ce,
1453 0x0330, 0x0103, 0x0165, 0x0356, 0x01a9, 0x039a, 0x03fc, 0x01cf,
1454 0x0062, 0x0251, 0x0237, 0x0004, 0x02fb, 0x00c8, 0x00ae, 0x029d,
1455 0x0363, 0x0150, 0x0136, 0x0305, 0x01fa, 0x03c9, 0x03af, 0x019c,
1456 0x0053, 0x0260, 0x0206, 0x0035, 0x02ca, 0x00f9, 0x009f, 0x02ac,
1457 0x0352, 0x0161, 0x0107, 0x0334, 0x01cb, 0x03f8, 0x039e, 0x01ad,
1458 0x00c4, 0x02f7, 0x0291, 0x00a2, 0x025d, 0x006e, 0x0008, 0x023b,
1459 0x03c5, 0x01f6, 0x0190, 0x03a3, 0x015c, 0x036f, 0x0309, 0x013a,
1460 0x00f5, 0x02c6, 0x02a0, 0x0093, 0x026c, 0x005f, 0x0039, 0x020a,
1461 0x03f4, 0x01c7, 0x01a1, 0x0392, 0x016d, 0x035e, 0x0338, 0x010b,
1462 0x00a6, 0x0295, 0x02f3, 0x00c0, 0x023f, 0x000c, 0x006a, 0x0259,
1463 0x03a7, 0x0194, 0x01f2, 0x03c1, 0x013e, 0x030d, 0x036b, 0x0158,
1464 0x0097, 0x02a4, 0x02c2, 0x00f1, 0x020e, 0x003d, 0x005b, 0x0268,
1465 0x0396, 0x01a5, 0x01c3, 0x03f0, 0x010f, 0x033c, 0x035a, 0x0169,
1466 0x0188, 0x03bb, 0x03dd, 0x01ee, 0x0311, 0x0122, 0x0144, 0x0377,
1467 0x0289, 0x00ba, 0x00dc, 0x02ef, 0x0010, 0x0223, 0x0245, 0x0076,
1468 0x01b9, 0x038a, 0x03ec, 0x01df, 0x0320, 0x0113, 0x0175, 0x0346,
1469 0x02b8, 0x008b, 0x00ed, 0x02de, 0x0021, 0x0212, 0x0274, 0x0047,
1470 0x01ea, 0x03d9, 0x03bf, 0x018c, 0x0373, 0x0140, 0x0126, 0x0315,
1471 0x02eb, 0x00d8, 0x00be, 0x028d, 0x0072, 0x0241, 0x0227, 0x0014,
1472 0x01db, 0x03e8, 0x038e, 0x01bd, 0x0342, 0x0171, 0x0117, 0x0324,
1473 0x02da, 0x00e9, 0x008f, 0x02bc, 0x0043, 0x0270, 0x0216, 0x0025,
1474 0x014c, 0x037f, 0x0319, 0x012a, 0x03d5, 0x01e6, 0x0180, 0x03b3,
1475 0x024d, 0x007e, 0x0018, 0x022b, 0x00d4, 0x02e7, 0x0281, 0x00b2,
1476 0x017d, 0x034e, 0x0328, 0x011b, 0x03e4, 0x01d7, 0x01b1, 0x0382,
1477 0x027c, 0x004f, 0x0029, 0x021a, 0x00e5, 0x02d6, 0x02b0, 0x0083,
1478 0x012e, 0x031d, 0x037b, 0x0148, 0x03b7, 0x0184, 0x01e2, 0x03d1,
1479 0x022f, 0x001c, 0x007a, 0x0249, 0x00b6, 0x0285, 0x02e3, 0x00d0,
1480 0x011f, 0x032c, 0x034a, 0x0179, 0x0386, 0x01b5, 0x01d3, 0x03e0,
1481 0x021e, 0x002d, 0x004b, 0x0278, 0x0087, 0x02b4, 0x02d2, 0x00e1,
1484 /* update the data block's CRC-10 remainder one byte at a time */
1486 update_crc10_by_bytes(guint16 crc10_accum, const guint8 *data_blk_ptr,
1491 for (i = 0; i < data_blk_size; i++) {
1492 crc10_accum = ((crc10_accum << 8) & 0x3ff)
1493 ^ byte_crc10_table[( crc10_accum >> 2) & 0xff]
1499 static const value_string st_vals[] = {
1507 #define OAM_TYPE_FM 1 /* Fault Management */
1508 #define OAM_TYPE_PM 2 /* Performance Management */
1509 #define OAM_TYPE_AD 8 /* Activation/Deactivation */
1511 static const value_string oam_type_vals[] = {
1512 { OAM_TYPE_FM, "Fault Management" },
1513 { OAM_TYPE_PM, "Performance Management" },
1514 { OAM_TYPE_AD, "Activation/Deactivation" },
1518 static const value_string ft_fm_vals[] = {
1519 { 0, "Alarm Indication Signal" },
1520 { 1, "Far End Receive Failure" },
1521 { 8, "OAM Cell Loopback" },
1522 { 4, "Continuity Check" },
1526 static const value_string ft_pm_vals[] = {
1527 { 0, "Forward Monitoring" },
1528 { 1, "Backward Reporting" },
1529 { 2, "Monitoring and Reporting" },
1533 static const value_string ft_ad_vals[] = {
1534 { 0, "Performance Monitoring" },
1535 { 1, "Continuity Check" },
1541 * Check for OAM cells.
1542 * OAM F4 is VCI 3 or 4 and PT 0X0.
1545 gboolean atm_is_oam_cell(const guint16 vci, const guint8 pt)
1547 return (((vci == 3 || vci == 4) && ((pt & 0x5) == 0))
1548 || ((pt & 0x6) == 0x4));
1553 dissect_atm_cell(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1554 proto_tree *atm_tree, guint aal, gboolean nni,
1555 gboolean crc_stripped)
1558 proto_tree *aal_tree;
1565 guint16 aal3_4_hdr, aal3_4_trlr;
1570 const pwatm_private_data_t * pwpd = pinfo->private_data;
1575 * FF: ITU-T I.361 (Section 2.2) defines the cell header format
1576 * and encoding at UNI reference point as:
1591 octet = tvb_get_guint8(tvb, 0);
1592 proto_tree_add_text(atm_tree, tvb, 0, 1, "GFC: 0x%x", octet >> 4);
1593 vpi = (octet & 0xF) << 4;
1594 octet = tvb_get_guint8(tvb, 1);
1596 proto_tree_add_uint(atm_tree, hf_atm_vpi, tvb, 0, 2, vpi);
1599 * FF: ITU-T I.361 (Section 2.3) defines the cell header format
1600 * and encoding at NNI reference point as:
1615 octet = tvb_get_guint8(tvb, 0);
1617 octet = tvb_get_guint8(tvb, 1);
1618 vpi |= (octet & 0xF0) >> 4;
1619 proto_tree_add_uint(atm_tree, hf_atm_vpi, tvb, 0, 2, vpi);
1622 vci = (octet & 0x0F) << 12;
1623 octet = tvb_get_guint8(tvb, 2);
1625 octet = tvb_get_guint8(tvb, 3);
1627 proto_tree_add_uint(atm_tree, hf_atm_vci, tvb, 1, 3, vci);
1628 pt = (octet >> 1) & 0x7;
1629 proto_tree_add_text(atm_tree, tvb, 3, 1, "Payload Type: %s",
1630 val_to_str(pt, atm_pt_vals, "Unknown (%u)"));
1631 proto_tree_add_text(atm_tree, tvb, 3, 1, "Cell Loss Priority: %s",
1632 (octet & 0x01) ? "Low priority" : "High priority");
1634 if (!crc_stripped) {
1636 * FF: parse the Header Error Check (HEC).
1638 ti = proto_tree_add_text(atm_tree, tvb, 4, 1,
1639 "Header Error Check: 0x%02x",
1640 tvb_get_guint8(tvb, 4));
1641 err = get_header_err(tvb_get_ptr(tvb, 0, 5));
1642 if (err == NO_ERROR_DETECTED)
1643 proto_item_append_text(ti, " (correct)");
1644 else if (err == UNCORRECTIBLE_ERROR)
1645 proto_item_append_text(ti, " (uncorrectable error)");
1647 proto_item_append_text(ti, " (error in bit %d)", err);
1651 * FF: in some encapsulation modes (e.g. RFC 4717, ATM N-to-One
1652 * Cell Mode) the Header Error Check (HEC) field is stripped.
1653 * So we do nothing here.
1660 offset = 0; /* For PWs. Header is decoded by PW dissector.*/
1661 pwpd = pinfo->private_data;
1668 * Check for OAM cells.
1669 * XXX - do this for all AAL values, overriding whatever information
1670 * Wiretap got from the file?
1672 if (aal == AAL_USER) {
1673 if (atm_is_oam_cell(vci,pt)) {
1681 col_set_str(pinfo->cinfo, COL_PROTOCOL, "AAL1");
1682 if (check_col(pinfo->cinfo, COL_INFO))
1683 col_clear(pinfo->cinfo, COL_INFO);
1684 ti = proto_tree_add_item(tree, proto_aal1, tvb, offset, -1, FALSE);
1685 aal_tree = proto_item_add_subtree(ti, ett_aal1);
1686 octet = tvb_get_guint8(tvb, offset);
1687 proto_tree_add_text(aal_tree, tvb, offset, 1, "CSI: %u", octet >> 7);
1688 proto_tree_add_text(aal_tree, tvb, offset, 1, "Sequence Count: %u",
1689 (octet >> 4) & 0x7);
1690 if (check_col(pinfo->cinfo, COL_INFO)) {
1691 col_add_fstr(pinfo->cinfo, COL_INFO, "Sequence count = %u",
1692 (octet >> 4) & 0x7);
1694 proto_tree_add_text(aal_tree, tvb, offset, 1, "CRC: 0x%x",
1695 (octet >> 1) & 0x7);
1696 proto_tree_add_text(aal_tree, tvb, offset, 1, "Parity: %u",
1700 proto_tree_add_text(aal_tree, tvb, offset, 47, "Payload");
1705 * XXX - or should this be the CS PDU?
1707 col_set_str(pinfo->cinfo, COL_PROTOCOL, "AAL3/4");
1708 if (check_col(pinfo->cinfo, COL_INFO))
1709 col_clear(pinfo->cinfo, COL_INFO);
1710 ti = proto_tree_add_item(tree, proto_aal3_4, tvb, offset, -1, FALSE);
1711 aal_tree = proto_item_add_subtree(ti, ett_aal3_4);
1712 aal3_4_hdr = tvb_get_ntohs(tvb, offset);
1713 if (check_col(pinfo->cinfo, COL_INFO)) {
1714 col_add_fstr(pinfo->cinfo, COL_INFO, "%s, sequence number = %u",
1715 val_to_str(aal3_4_hdr >> 14, st_vals, "Unknown (%u)"),
1716 (aal3_4_hdr >> 10) & 0xF);
1718 proto_tree_add_text(aal_tree, tvb, offset, 2, "Segment Type: %s",
1719 val_to_str(aal3_4_hdr >> 14, st_vals, "Unknown (%u)"));
1720 proto_tree_add_text(aal_tree, tvb, offset, 2, "Sequence Number: %u",
1721 (aal3_4_hdr >> 10) & 0xF);
1722 proto_tree_add_text(aal_tree, tvb, offset, 2, "Multiplex ID: %u",
1723 aal3_4_hdr & 0x3FF);
1726 proto_tree_add_text(aal_tree, tvb, offset, 44, "Information");
1729 aal3_4_trlr = tvb_get_ntohs(tvb, offset);
1730 proto_tree_add_text(aal_tree, tvb, offset, 2, "Length Indicator: %u",
1731 (aal3_4_trlr >> 10) & 0x3F);
1732 length = tvb_length_remaining(tvb, 5);
1733 crc10 = update_crc10_by_bytes(0, tvb_get_ptr(tvb, 5, length),
1735 proto_tree_add_text(aal_tree, tvb, offset, 2, "CRC: 0x%03x (%s)",
1736 aal3_4_trlr & 0x3FF,
1737 (crc10 == 0) ? "correct" : "incorrect");
1741 if (NULL == pwpd || pwpd->enable_fill_columns_by_atm_dissector)
1743 col_set_str(pinfo->cinfo, COL_PROTOCOL, "OAM AAL");
1744 if (check_col(pinfo->cinfo, COL_INFO))
1745 col_clear(pinfo->cinfo, COL_INFO);
1747 ti = proto_tree_add_item(tree, proto_oamaal, tvb, offset, -1, FALSE);
1748 aal_tree = proto_item_add_subtree(ti, ett_oamaal);
1749 octet = tvb_get_guint8(tvb, offset);
1750 if (NULL == pwpd || pwpd->enable_fill_columns_by_atm_dissector)
1752 if (check_col(pinfo->cinfo, COL_INFO))
1753 col_add_fstr(pinfo->cinfo, COL_INFO, "%s",
1754 val_to_str(octet >> 4, oam_type_vals, "Unknown (%u)"));
1756 proto_tree_add_text(aal_tree, tvb, offset, 1, "OAM Type: %s",
1757 val_to_str(octet >> 4, oam_type_vals, "Unknown (%u)"));
1758 switch (octet >> 4) {
1761 proto_tree_add_text(aal_tree, tvb, offset, 1, "Function Type: %s",
1762 val_to_str(octet & 0x0F, ft_fm_vals, "Unknown (%u)"));
1766 proto_tree_add_text(aal_tree, tvb, offset, 1, "Function Type: %s",
1767 val_to_str(octet & 0x0F, ft_pm_vals, "Unknown (%u)"));
1771 proto_tree_add_text(aal_tree, tvb, offset, 1, "Function Type: %s",
1772 val_to_str(octet & 0x0F, ft_ad_vals, "Unknown (%u)"));
1776 proto_tree_add_text(aal_tree, tvb, offset, 1, "Function Type: %u",
1782 proto_tree_add_text(aal_tree, tvb, offset, 45, "Function-specific information");
1785 length = tvb_length_remaining(tvb, 5);
1786 crc10 = update_crc10_by_bytes(0, tvb_get_ptr(tvb, 5, length),
1788 oam_crc = tvb_get_ntohs(tvb, offset);
1789 proto_tree_add_text(aal_tree, tvb, offset, 2, "CRC-10: 0x%03x (%s)",
1791 (crc10 == 0) ? "correct" : "incorrect");
1795 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
1796 call_dissector(data_handle, next_tvb, pinfo, tree);
1802 dissect_atm_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1805 proto_tree *atm_tree = NULL;
1806 proto_item *atm_ti = NULL;
1807 gboolean pseudowire_mode = (NULL != pinfo->private_data);
1809 if ( pinfo->pseudo_header->atm.aal == AAL_5 &&
1810 pinfo->pseudo_header->atm.type == TRAF_LANE &&
1811 dissect_lanesscop ) {
1812 pinfo->pseudo_header->atm.aal = AAL_SIGNALLING;
1815 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATM");
1817 if (!pseudowire_mode) {
1818 switch (pinfo->pseudo_header->atm.channel) {
1821 /* Traffic from DTE to DCE. */
1822 if (check_col(pinfo->cinfo, COL_RES_DL_DST))
1823 col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DCE");
1824 if (check_col(pinfo->cinfo, COL_RES_DL_SRC))
1825 col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DTE");
1829 /* Traffic from DCE to DTE. */
1830 if (check_col(pinfo->cinfo, COL_RES_DL_DST))
1831 col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DTE");
1832 if (check_col(pinfo->cinfo, COL_RES_DL_SRC))
1833 col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DCE");
1838 if (check_col(pinfo->cinfo, COL_INFO)) {
1839 if (pinfo->pseudo_header->atm.aal == AAL_5) {
1840 col_add_fstr(pinfo->cinfo, COL_INFO, "AAL5 %s",
1841 val_to_str(pinfo->pseudo_header->atm.type, aal5_hltype_vals,
1842 "Unknown traffic type (%u)"));
1844 col_add_str(pinfo->cinfo, COL_INFO,
1845 val_to_str(pinfo->pseudo_header->atm.aal, aal_vals,
1846 "Unknown AAL (%u)"));
1851 atm_ti = proto_tree_add_protocol_format(tree, proto_atm, tvb, 0, 0, "ATM");
1852 atm_tree = proto_item_add_subtree(atm_ti, ett_atm);
1854 if (!pseudowire_mode) {
1855 switch (pinfo->pseudo_header->atm.channel) {
1858 /* Traffic from DTE to DCE. */
1859 proto_tree_add_text(atm_tree, tvb, 0, 0, "Channel: DTE->DCE");
1863 /* Traffic from DCE to DTE. */
1864 proto_tree_add_text(atm_tree, tvb, 0, 0, "Channel: DCE->DTE");
1868 /* Sniffers shouldn't provide anything other than 0 or 1. */
1869 proto_tree_add_text(atm_tree, tvb, 0, 0, "Channel: %u",
1870 pinfo->pseudo_header->atm.channel);
1875 proto_tree_add_uint_format_value(atm_tree, hf_atm_aal, tvb, 0, 0,
1876 pinfo->pseudo_header->atm.aal,
1878 val_to_str(pinfo->pseudo_header->atm.aal, aal_vals,
1879 "Unknown AAL (%u)"));
1881 if (pinfo->pseudo_header->atm.flags & ATM_RAW_CELL) {
1882 /* This is a single cell, with the cell header at the beginning. */
1883 proto_item_set_len(atm_ti, 5);
1884 dissect_atm_cell(tvb, pinfo, tree, atm_tree,
1885 pinfo->pseudo_header->atm.aal, FALSE, FALSE);
1887 /* This is a reassembled PDU. */
1888 dissect_reassembled_pdu(tvb, pinfo, tree, atm_tree, atm_ti, truncated);
1893 dissect_atm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1895 dissect_atm_common(tvb, pinfo, tree, TRUE);
1899 dissect_atm_untruncated(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1901 dissect_atm_common(tvb, pinfo, tree, FALSE);
1905 dissect_atm_oam_cell(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1907 proto_tree *atm_tree = NULL;
1908 proto_item *atm_ti = NULL;
1909 gboolean pseudowire_mode = (NULL != pinfo->private_data);
1911 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATM");
1913 if (!pseudowire_mode) {
1915 atm_ti = proto_tree_add_protocol_format(tree, proto_atm, tvb, 0, 0, "ATM");
1916 atm_tree = proto_item_add_subtree(atm_ti, ett_atm);
1920 dissect_atm_cell(tvb, pinfo, tree, atm_tree, AAL_OAMCELL, FALSE, FALSE);
1925 proto_register_atm(void)
1927 static hf_register_info hf[] = {
1929 { "AAL", "atm.aal", FT_UINT8, BASE_DEC, VALS(aal_vals), 0x0,
1933 { "VPI", "atm.vpi", FT_UINT8, BASE_DEC, NULL, 0x0,
1937 { "VCI", "atm.vci", FT_UINT16, BASE_DEC, NULL, 0x0,
1941 { "CID", "atm.cid", FT_UINT8, BASE_DEC, NULL, 0x0,
1945 static gint *ett[] = {
1952 &ett_atm_lane_lc_lan_dest,
1953 &ett_atm_lane_lc_lan_dest_rd,
1954 &ett_atm_lane_lc_flags,
1955 &ett_atm_lane_lc_tlv,
1958 module_t *atm_module;
1960 proto_atm = proto_register_protocol("ATM", "ATM", "atm");
1961 proto_aal1 = proto_register_protocol("ATM AAL1", "AAL1", "aal1");
1962 proto_aal3_4 = proto_register_protocol("ATM AAL3/4", "AAL3/4", "aal3_4");
1963 proto_oamaal = proto_register_protocol("ATM OAM AAL", "OAM AAL", "oamaal");
1964 proto_register_field_array(proto_atm, hf, array_length(hf));
1965 proto_register_subtree_array(ett, array_length(ett));
1967 proto_ilmi = proto_register_protocol("ILMI", "ILMI", "ilmi");
1969 register_dissector("ilmi", dissect_ilmi, proto_ilmi);
1971 proto_atm_lane = proto_register_protocol("ATM LAN Emulation",
1972 "ATM LANE", "lane");
1974 register_dissector("lane", dissect_lane, proto_atm_lane);
1975 register_dissector("atm_untruncated", dissect_atm_untruncated, proto_atm);
1976 register_dissector("atm_truncated", dissect_atm, proto_atm);
1977 register_dissector("atm_oam_cell", dissect_atm_oam_cell, proto_oamaal);
1979 atm_module = prefs_register_protocol ( proto_atm, NULL );
1980 prefs_register_bool_preference ( atm_module, "dissect_lane_as_sscop", "Dissect LANE as SSCOP",
1981 "Autodection between LANE and SSCOP is hard. As default LANE is preferred",
1982 &dissect_lanesscop);
1986 proto_reg_handoff_atm(void)
1988 dissector_handle_t atm_handle, atm_untruncated_handle;
1991 * Get handles for the Ethernet, Token Ring, Frame Relay, LLC,
1992 * SSCOP, LANE, and ILMI dissectors.
1994 eth_withoutfcs_handle = find_dissector("eth_withoutfcs");
1995 tr_handle = find_dissector("tr");
1996 fr_handle = find_dissector("fr");
1997 llc_handle = find_dissector("llc");
1998 sscop_handle = find_dissector("sscop");
1999 lane_handle = find_dissector("lane");
2000 ilmi_handle = find_dissector("ilmi");
2001 ppp_handle = find_dissector("ppp");
2002 eth_handle = find_dissector("eth");
2003 ip_handle = find_dissector("ip");
2004 data_handle = find_dissector("data");
2005 fp_handle = find_dissector("fp");
2007 atm_handle = create_dissector_handle(dissect_atm, proto_atm);
2008 dissector_add("wtap_encap", WTAP_ENCAP_ATM_PDUS, atm_handle);
2010 atm_untruncated_handle = create_dissector_handle(dissect_atm_untruncated,
2012 dissector_add("wtap_encap", WTAP_ENCAP_ATM_PDUS_UNTRUNCATED,
2013 atm_untruncated_handle);