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.
30 #include <epan/packet.h>
32 #include <epan/addr_resolv.h>
33 #include <epan/ppptypes.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"
40 #include <epan/prefs.h>
41 #include "packet-pw-atm.h"
43 static int proto_atm = -1;
44 static int hf_atm_aal = -1;
45 static int hf_atm_vpi = -1;
46 static int hf_atm_vci = -1;
47 static int hf_atm_cid = -1;
48 static int proto_atm_lane = -1;
49 static int proto_ilmi = -1;
50 static int proto_aal1 = -1;
51 static int proto_aal3_4 = -1;
52 static int proto_oamaal = -1;
54 static gint ett_atm = -1;
55 static gint ett_atm_lane = -1;
56 static gint ett_atm_lane_lc_lan_dest = -1;
57 static gint ett_atm_lane_lc_lan_dest_rd = -1;
58 static gint ett_atm_lane_lc_flags = -1;
59 static gint ett_atm_lane_lc_tlv = -1;
60 static gint ett_ilmi = -1;
61 static gint ett_aal1 = -1;
62 static gint ett_aal3_4 = -1;
63 static gint ett_oamaal = -1;
65 static dissector_handle_t eth_withoutfcs_handle;
66 static dissector_handle_t tr_handle;
67 static dissector_handle_t fr_handle;
68 static dissector_handle_t llc_handle;
69 static dissector_handle_t sscop_handle;
70 static dissector_handle_t lane_handle;
71 static dissector_handle_t ilmi_handle;
72 static dissector_handle_t fp_handle;
73 static dissector_handle_t ppp_handle;
74 static dissector_handle_t eth_handle;
75 static dissector_handle_t ip_handle;
76 static dissector_handle_t data_handle;
77 static dissector_handle_t gprs_ns_handle;
79 static gboolean dissect_lanesscop = FALSE;
81 static gint unknown_aal2_type = TRAF_UNKNOWN;
86 * http://www.atmforum.org/atmforum/specs/approved.html
88 * for a number of ATM Forum specifications, e.g. the LAN Emulation
89 * over ATM 1.0 spec, whence I got most of this.
92 /* LE Control opcodes */
93 #define LE_CONFIGURE_REQUEST 0x0001
94 #define LE_CONFIGURE_RESPONSE 0x0101
95 #define LE_JOIN_REQUEST 0x0002
96 #define LE_JOIN_RESPONSE 0x0102
97 #define READY_QUERY 0x0003
98 #define READY_IND 0x0103
99 #define LE_REGISTER_REQUEST 0x0004
100 #define LE_REGISTER_RESPONSE 0x0104
101 #define LE_UNREGISTER_REQUEST 0x0005
102 #define LE_UNREGISTER_RESPONSE 0x0105
103 #define LE_ARP_REQUEST 0x0006
104 #define LE_ARP_RESPONSE 0x0106
105 #define LE_FLUSH_REQUEST 0x0007
106 #define LE_FLUSH_RESPONSE 0x0107
107 #define LE_NARP_REQUEST 0x0008
108 #define LE_TOPOLOGY_REQUEST 0x0009
109 #define LE_VERIFY_REQUEST 0x000A
110 #define LE_VERIFY_RESPONSE 0x010A
112 static const value_string le_control_opcode_vals[] = {
113 { LE_CONFIGURE_REQUEST, "LE_CONFIGURE_REQUEST" },
114 { LE_CONFIGURE_RESPONSE, "LE_CONFIGURE_RESPONSE" },
115 { LE_JOIN_REQUEST, "LE_JOIN_REQUEST" },
116 { LE_JOIN_RESPONSE, "LE_JOIN_RESPONSE" },
117 { READY_QUERY, "READY_QUERY" },
118 { READY_IND, "READY_IND" },
119 { LE_REGISTER_REQUEST, "LE_REGISTER_REQUEST" },
120 { LE_REGISTER_RESPONSE, "LE_REGISTER_RESPONSE" },
121 { LE_UNREGISTER_REQUEST, "LE_UNREGISTER_REQUEST" },
122 { LE_UNREGISTER_RESPONSE, "LE_UNREGISTER_RESPONSE" },
123 { LE_ARP_REQUEST, "LE_ARP_REQUEST" },
124 { LE_ARP_RESPONSE, "LE_ARP_RESPONSE" },
125 { LE_FLUSH_REQUEST, "LE_FLUSH_REQUEST" },
126 { LE_FLUSH_RESPONSE, "LE_FLUSH_RESPONSE" },
127 { LE_NARP_REQUEST, "LE_NARP_REQUEST" },
128 { LE_TOPOLOGY_REQUEST, "LE_TOPOLOGY_REQUEST" },
129 { LE_VERIFY_REQUEST, "LE_VERIFY_REQUEST" },
130 { LE_VERIFY_RESPONSE, "LE_VERIFY_RESPONSE" },
134 /* LE Control statuses */
135 static const value_string le_control_status_vals[] = {
137 { 1, "Version not supported" },
138 { 2, "Invalid request parameters" },
139 { 4, "Duplicate LAN destination registration" },
140 { 5, "Duplicate ATM address" },
141 { 6, "Insufficient resources to grant request" },
142 { 7, "Access denied" },
143 { 8, "Invalid REQUESTOR-ID" },
144 { 9, "Invalid LAN destination" },
145 { 10, "Invalid ATM address" },
146 { 20, "No configuration" },
147 { 21, "LE_CONFIGURE error" },
148 { 22, "Insufficient information" },
149 { 24, "TLV not found" },
153 /* LE Control LAN destination tags */
154 #define TAG_NOT_PRESENT 0x0000
155 #define TAG_MAC_ADDRESS 0x0001
156 #define TAG_ROUTE_DESCRIPTOR 0x0002
158 static const value_string le_control_landest_tag_vals[] = {
159 { TAG_NOT_PRESENT, "Not present" },
160 { TAG_MAC_ADDRESS, "MAC address" },
161 { TAG_ROUTE_DESCRIPTOR, "Route descriptor" },
165 /* LE Control LAN types */
166 #define LANT_UNSPEC 0x00
167 #define LANT_802_3 0x01
168 #define LANT_802_5 0x02
170 static const value_string le_control_lan_type_vals[] = {
171 { LANT_UNSPEC, "Unspecified" },
172 { LANT_802_3, "Ethernet/802.3" },
173 { LANT_802_5, "802.5" },
177 static const value_string le_control_frame_size_vals[] = {
178 { 0x00, "Unspecified" },
179 { 0x01, "1516/1528/1580/1592" },
180 { 0x02, "4544/4556/1580/1592" },
181 { 0x03, "9234/9246" },
182 { 0x04, "18190/18202" },
187 dissect_le_client(tvbuff_t *tvb, proto_tree *tree)
190 proto_tree *lane_tree;
193 ti = proto_tree_add_protocol_format(tree, proto_atm_lane, tvb, 0, 2, "ATM LANE");
194 lane_tree = proto_item_add_subtree(ti, ett_atm_lane);
196 proto_tree_add_text(lane_tree, tvb, 0, 2, "LE Client: 0x%04X",
197 tvb_get_ntohs(tvb, 0));
202 dissect_lan_destination(tvbuff_t *tvb, int offset, const char *type, proto_tree *tree)
205 proto_tree *dest_tree;
208 guint16 route_descriptor;
210 td = proto_tree_add_text(tree, tvb, offset, 8, "%s LAN destination",
212 dest_tree = proto_item_add_subtree(td, ett_atm_lane_lc_lan_dest);
213 tag = tvb_get_ntohs(tvb, offset);
214 proto_tree_add_text(dest_tree, tvb, offset, 2, "Tag: %s",
215 val_to_str(tag, le_control_landest_tag_vals,
216 "Unknown (0x%04X)"));
221 case TAG_MAC_ADDRESS:
222 proto_tree_add_text(dest_tree, tvb, offset, 6, "MAC address: %s",
223 tvb_ether_to_str(tvb, offset));
226 case TAG_ROUTE_DESCRIPTOR:
228 route_descriptor = tvb_get_ntohs(tvb, offset);
229 proto_tree_add_text(dest_tree, tvb, offset, 2, "Route descriptor: 0x%02X",
231 rd_tree = proto_item_add_subtree(td, ett_atm_lane_lc_lan_dest_rd);
232 proto_tree_add_text(rd_tree, tvb, offset, 2, "%s",
233 decode_numeric_bitfield(route_descriptor, 0xFFF0, 2*8,
235 proto_tree_add_text(rd_tree, tvb, offset, 2, "%s",
236 decode_numeric_bitfield(route_descriptor, 0x000F, 2*8,
237 "Bridge number = %u"));
243 * TLV values in LE Control frames.
245 #define TLV_TYPE(oui, ident) (((oui) << 8) | (ident))
247 #define LE_CONTROL_TIMEOUT TLV_TYPE(OUI_ATM_FORUM, 0x01)
248 #define LE_MAX_UNK_FRAME_COUNT TLV_TYPE(OUI_ATM_FORUM, 0x02)
249 #define LE_MAX_UNK_FRAME_TIME TLV_TYPE(OUI_ATM_FORUM, 0x03)
250 #define LE_VCC_TIMEOUT_PERIOD TLV_TYPE(OUI_ATM_FORUM, 0x04)
251 #define LE_MAX_RETRY_COUNT TLV_TYPE(OUI_ATM_FORUM, 0x05)
252 #define LE_AGING_TIME TLV_TYPE(OUI_ATM_FORUM, 0x06)
253 #define LE_FORWARD_DELAY_TIME TLV_TYPE(OUI_ATM_FORUM, 0x07)
254 #define LE_EXPECTED_ARP_RESPONSE_TIME TLV_TYPE(OUI_ATM_FORUM, 0x08)
255 #define LE_FLUSH_TIMEOUT TLV_TYPE(OUI_ATM_FORUM, 0x09)
256 #define LE_PATH_SWITCHING_DELAY TLV_TYPE(OUI_ATM_FORUM, 0x0A)
257 #define LE_LOCAL_SEGMENT_ID TLV_TYPE(OUI_ATM_FORUM, 0x0B)
258 #define LE_MCAST_SEND_VCC_TYPE TLV_TYPE(OUI_ATM_FORUM, 0x0C)
259 #define LE_MCAST_SEND_VCC_AVGRATE TLV_TYPE(OUI_ATM_FORUM, 0x0D)
260 #define LE_MCAST_SEND_VCC_PEAKRATE TLV_TYPE(OUI_ATM_FORUM, 0x0E)
261 #define LE_CONN_COMPLETION_TIMER TLV_TYPE(OUI_ATM_FORUM, 0x0F)
262 #define LE_CONFIG_FRAG_INFO TLV_TYPE(OUI_ATM_FORUM, 0x10)
263 #define LE_LAYER_3_ADDRESS TLV_TYPE(OUI_ATM_FORUM, 0x11)
264 #define LE_ELAN_ID TLV_TYPE(OUI_ATM_FORUM, 0x12)
265 #define LE_SERVICE_CATEGORY TLV_TYPE(OUI_ATM_FORUM, 0x13)
266 #define LE_LLC_MUXED_ATM_ADDRESS TLV_TYPE(OUI_ATM_FORUM, 0x2B)
267 #define LE_X5_ADJUSTMENT TLV_TYPE(OUI_ATM_FORUM, 0x2C)
268 #define LE_PREFERRED_LES TLV_TYPE(OUI_ATM_FORUM, 0x2D)
270 static const value_string le_tlv_type_vals[] = {
271 { LE_CONTROL_TIMEOUT, "Control Time-out" },
272 { LE_MAX_UNK_FRAME_COUNT, "Maximum Unknown Frame Count" },
273 { LE_MAX_UNK_FRAME_TIME, "Maximum Unknown Frame Time" },
274 { LE_VCC_TIMEOUT_PERIOD, "VCC Time-out" },
275 { LE_MAX_RETRY_COUNT, "Maximum Retry Count" },
276 { LE_AGING_TIME, "Aging Time" },
277 { LE_FORWARD_DELAY_TIME, "Forwarding Delay Time" },
278 { LE_EXPECTED_ARP_RESPONSE_TIME, "Expected LE_ARP Response Time" },
279 { LE_FLUSH_TIMEOUT, "Flush Time-out" },
280 { LE_PATH_SWITCHING_DELAY, "Path Switching Delay" },
281 { LE_LOCAL_SEGMENT_ID, "Local Segment ID" },
282 { LE_MCAST_SEND_VCC_TYPE, "Mcast Send VCC Type" },
283 { LE_MCAST_SEND_VCC_AVGRATE, "Mcast Send VCC AvgRate" },
284 { LE_MCAST_SEND_VCC_PEAKRATE, "Mcast Send VCC PeakRate" },
285 { LE_CONN_COMPLETION_TIMER, "Connection Completion Timer" },
286 { LE_CONFIG_FRAG_INFO, "Config Frag Info" },
287 { LE_LAYER_3_ADDRESS, "Layer 3 Address" },
288 { LE_ELAN_ID, "ELAN ID" },
289 { LE_SERVICE_CATEGORY, "Service Category" },
290 { LE_LLC_MUXED_ATM_ADDRESS, "LLC-muxed ATM Address" },
291 { LE_X5_ADJUSTMENT, "X5 Adjustment" },
292 { LE_PREFERRED_LES, "Preferred LES" },
297 dissect_le_control_tlvs(tvbuff_t *tvb, int offset, guint num_tlvs,
303 proto_tree *tlv_tree;
305 while (num_tlvs != 0) {
306 tlv_type = tvb_get_ntohl(tvb, offset);
307 tlv_length = tvb_get_guint8(tvb, offset+4);
308 ttlv = proto_tree_add_text(tree, tvb, offset, 5+tlv_length, "TLV type: %s",
309 val_to_str(tlv_type, le_tlv_type_vals, "Unknown (0x%08x)"));
310 tlv_tree = proto_item_add_subtree(ttlv, ett_atm_lane_lc_tlv);
311 proto_tree_add_text(tlv_tree, tvb, offset, 4, "TLV Type: %s",
312 val_to_str(tlv_type, le_tlv_type_vals, "Unknown (0x%08x)"));
313 proto_tree_add_text(tlv_tree, tvb, offset+4, 1, "TLV Length: %u", tlv_length);
314 offset += 5+tlv_length;
320 dissect_le_configure_join_frame(tvbuff_t *tvb, int offset, proto_tree *tree)
325 dissect_lan_destination(tvb, offset, "Source", tree);
328 dissect_lan_destination(tvb, offset, "Target", tree);
331 proto_tree_add_text(tree, tvb, offset, 20, "Source ATM Address: %s",
332 tvb_bytes_to_str(tvb, offset, 20));
335 proto_tree_add_text(tree, tvb, offset, 1, "LAN type: %s",
336 val_to_str(tvb_get_guint8(tvb, offset), le_control_lan_type_vals,
337 "Unknown (0x%02X)"));
340 proto_tree_add_text(tree, tvb, offset, 1, "Maximum frame size: %s",
341 val_to_str(tvb_get_guint8(tvb, offset), le_control_frame_size_vals,
342 "Unknown (0x%02X)"));
345 num_tlvs = tvb_get_guint8(tvb, offset);
346 proto_tree_add_text(tree, tvb, offset, 1, "Number of TLVs: %u", num_tlvs);
349 name_size = tvb_get_guint8(tvb, offset);
350 proto_tree_add_text(tree, tvb, offset, 1, "ELAN name size: %u", name_size);
353 proto_tree_add_text(tree, tvb, offset, 20, "Target ATM Address: %s",
354 tvb_bytes_to_str(tvb, offset, 20));
359 if (name_size != 0) {
360 proto_tree_add_text(tree, tvb, offset, name_size, "ELAN name: %s",
361 tvb_bytes_to_str(tvb, offset, name_size));
365 dissect_le_control_tlvs(tvb, offset, num_tlvs, tree);
369 dissect_le_registration_frame(tvbuff_t *tvb, int offset, proto_tree *tree)
373 dissect_lan_destination(tvb, offset, "Source", tree);
376 dissect_lan_destination(tvb, offset, "Target", tree);
379 proto_tree_add_text(tree, tvb, offset, 20, "Source ATM Address: %s",
380 tvb_bytes_to_str(tvb, offset, 20));
386 num_tlvs = tvb_get_guint8(tvb, offset);
387 proto_tree_add_text(tree, tvb, offset, 1, "Number of TLVs: %u", num_tlvs);
393 dissect_le_control_tlvs(tvb, offset, num_tlvs, tree);
397 dissect_le_arp_frame(tvbuff_t *tvb, int offset, proto_tree *tree)
401 dissect_lan_destination(tvb, offset, "Source", tree);
404 dissect_lan_destination(tvb, offset, "Target", tree);
407 proto_tree_add_text(tree, tvb, offset, 20, "Source ATM Address: %s",
408 tvb_bytes_to_str(tvb, offset, 20));
414 num_tlvs = tvb_get_guint8(tvb, offset);
415 proto_tree_add_text(tree, tvb, offset, 1, "Number of TLVs: %u", num_tlvs);
421 proto_tree_add_text(tree, tvb, offset, 20, "Target ATM Address: %s",
422 tvb_bytes_to_str(tvb, offset, 20));
428 dissect_le_control_tlvs(tvb, offset, num_tlvs, tree);
432 dissect_le_verify_frame(tvbuff_t *tvb, int offset, proto_tree *tree)
439 num_tlvs = tvb_get_guint8(tvb, offset);
440 proto_tree_add_text(tree, tvb, offset, 1, "Number of TLVs: %u", num_tlvs);
446 proto_tree_add_text(tree, tvb, offset, 20, "Target ATM Address: %s",
447 tvb_bytes_to_str(tvb, offset, 20));
453 dissect_le_control_tlvs(tvb, offset, num_tlvs, tree);
457 dissect_le_flush_frame(tvbuff_t *tvb, int offset, proto_tree *tree)
459 dissect_lan_destination(tvb, offset, "Source", tree);
462 dissect_lan_destination(tvb, offset, "Target", tree);
465 proto_tree_add_text(tree, tvb, offset, 20, "Source ATM Address: %s",
466 tvb_bytes_to_str(tvb, offset, 20));
472 proto_tree_add_text(tree, tvb, offset, 20, "Target ATM Address: %s",
473 tvb_bytes_to_str(tvb, offset, 20));
481 dissect_le_control(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
484 proto_tree *lane_tree = NULL;
487 proto_tree *flags_tree;
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 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s",
516 val_to_str(opcode, le_control_opcode_vals,
517 "Unknown opcode (0x%04X)"));
520 proto_tree_add_text(lane_tree, tvb, offset, 2, "Opcode: %s",
521 val_to_str(opcode, le_control_opcode_vals,
522 "Unknown (0x%04X)"));
526 if (opcode == READY_QUERY || opcode == READY_IND) {
527 /* There's nothing more in this packet. */
532 if (opcode & 0x0100) {
533 /* Response; decode status. */
534 proto_tree_add_text(lane_tree, tvb, offset, 2, "Status: %s",
535 val_to_str(tvb_get_ntohs(tvb, offset), le_control_status_vals,
536 "Unknown (0x%04X)"));
540 proto_tree_add_text(lane_tree, tvb, offset, 4, "Transaction ID: 0x%08X",
541 tvb_get_ntohl(tvb, offset));
544 proto_tree_add_text(lane_tree, tvb, offset, 2, "Requester LECID: 0x%04X",
545 tvb_get_ntohs(tvb, offset));
548 flags = tvb_get_ntohs(tvb, offset);
549 tf = proto_tree_add_text(lane_tree, tvb, offset, 2, "Flags: 0x%04X",
551 flags_tree = proto_item_add_subtree(tf, ett_atm_lane_lc_flags);
555 case LE_CONFIGURE_REQUEST:
556 case LE_CONFIGURE_RESPONSE:
557 proto_tree_add_text(flags_tree, tvb, offset, 2, "%s",
558 decode_boolean_bitfield(flags, 0x0002, 8*2,
559 "V2 capable", "Not V2 capable"));
561 dissect_le_configure_join_frame(tvb, offset, lane_tree);
564 case LE_JOIN_REQUEST:
565 case LE_JOIN_RESPONSE:
566 proto_tree_add_text(flags_tree, tvb, offset, 2, "%s",
567 decode_boolean_bitfield(flags, 0x0002, 8*2,
568 "V2 capable", "Not V2 capable"));
569 if (opcode == LE_JOIN_REQUEST) {
570 proto_tree_add_text(flags_tree, tvb, offset, 2, "%s",
571 decode_boolean_bitfield(flags, 0x0004, 8*2,
572 "Selective multicast", "No selective multicast"));
574 proto_tree_add_text(flags_tree, tvb, offset, 2, "%s",
575 decode_boolean_bitfield(flags, 0x0008, 8*2,
576 "V2 required", "V2 not required"));
578 proto_tree_add_text(flags_tree, tvb, offset, 2, "%s",
579 decode_boolean_bitfield(flags, 0x0080, 8*2,
580 "Proxy", "Not proxy"));
581 proto_tree_add_text(flags_tree, tvb, offset, 2, "%s",
582 decode_boolean_bitfield(flags, 0x0200, 8*2,
583 "Exclude explorer frames",
584 "Don't exclude explorer frames"));
586 dissect_le_configure_join_frame(tvb, offset, lane_tree);
589 case LE_REGISTER_REQUEST:
590 case LE_REGISTER_RESPONSE:
591 case LE_UNREGISTER_REQUEST:
592 case LE_UNREGISTER_RESPONSE:
594 dissect_le_registration_frame(tvb, offset, lane_tree);
598 case LE_ARP_RESPONSE:
599 case LE_NARP_REQUEST:
600 if (opcode != LE_NARP_REQUEST) {
601 proto_tree_add_text(flags_tree, tvb, offset, 2, "%s",
602 decode_boolean_bitfield(flags, 0x0001, 8*2,
603 "Remote address", "Local address"));
606 dissect_le_arp_frame(tvb, offset, lane_tree);
609 case LE_TOPOLOGY_REQUEST:
610 proto_tree_add_text(flags_tree, tvb, offset, 2, "%s",
611 decode_boolean_bitfield(flags, 0x0100, 8*2,
612 "Topology change", "No topology change"));
614 /* 92 reserved bytes */
617 case LE_VERIFY_REQUEST:
618 case LE_VERIFY_RESPONSE:
620 dissect_le_verify_frame(tvb, offset, lane_tree);
623 case LE_FLUSH_REQUEST:
624 case LE_FLUSH_RESPONSE:
626 dissect_le_flush_frame(tvb, offset, lane_tree);
633 capture_lane(const union wtap_pseudo_header *pseudo_header, const guchar *pd,
634 int len, packet_counts *ld)
636 /* Is it LE Control, 802.3, 802.5, or "none of the above"? */
637 switch (pseudo_header->atm.subtype) {
639 case TRAF_ST_LANE_802_3:
640 case TRAF_ST_LANE_802_3_MC:
641 /* Dissect as Ethernet */
642 capture_eth(pd, 2, len, ld);
645 case TRAF_ST_LANE_802_5:
646 case TRAF_ST_LANE_802_5_MC:
647 /* Dissect as Token-Ring */
648 capture_tr(pd, 2, len, ld);
658 dissect_lane(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
661 tvbuff_t *next_tvb_le_client;
663 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATM LANE");
665 /* Is it LE Control, 802.3, 802.5, or "none of the above"? */
666 switch (pinfo->pseudo_header->atm.subtype) {
668 case TRAF_ST_LANE_LE_CTRL:
669 dissect_le_control(tvb, pinfo, tree);
672 case TRAF_ST_LANE_802_3:
673 case TRAF_ST_LANE_802_3_MC:
674 col_set_str(pinfo->cinfo, COL_INFO, "LE Client - Ethernet/802.3");
675 dissect_le_client(tvb, tree);
677 /* Dissect as Ethernet */
678 next_tvb_le_client = tvb_new_subset_remaining(tvb, 2);
679 call_dissector(eth_withoutfcs_handle, next_tvb_le_client, pinfo, tree);
682 case TRAF_ST_LANE_802_5:
683 case TRAF_ST_LANE_802_5_MC:
684 col_set_str(pinfo->cinfo, COL_INFO, "LE Client - 802.5");
685 dissect_le_client(tvb, tree);
687 /* Dissect as Token-Ring */
688 next_tvb_le_client = tvb_new_subset_remaining(tvb, 2);
689 call_dissector(tr_handle, next_tvb_le_client, pinfo, tree);
693 /* Dump it as raw data. */
694 col_set_str(pinfo->cinfo, COL_INFO, "Unknown LANE traffic type");
695 next_tvb = tvb_new_subset_remaining(tvb, 0);
696 call_dissector(data_handle,next_tvb, pinfo, tree);
702 dissect_ilmi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
704 dissect_snmp_pdu(tvb, 0, pinfo, tree, proto_ilmi, ett_ilmi, ENC_BIG_ENDIAN);
708 static const value_string aal_vals[] = {
709 { AAL_UNKNOWN, "Unknown AAL" },
712 { AAL_3_4, "AAL3/4" },
714 { AAL_USER, "User AAL" },
715 { AAL_SIGNALLING, "Signalling AAL" },
716 { AAL_OAMCELL, "OAM cell" },
720 /* AAL5 higher-level traffic types */
721 static const value_string aal5_hltype_vals[] = {
722 { TRAF_UNKNOWN, "Unknown traffic type" },
723 { TRAF_LLCMX, "LLC multiplexed" },
724 { TRAF_VCMX, "VC multiplexed" },
725 { TRAF_LANE, "LANE" },
726 { TRAF_ILMI, "ILMI" },
727 { TRAF_FR, "Frame Relay" },
728 { TRAF_SPANS, "FORE SPANS" },
729 { TRAF_IPSILON, "Ipsilon" },
730 { TRAF_GPRS_NS, "GPRS NS" },
734 /* Traffic subtypes for VC multiplexed traffic */
735 static const value_string vcmx_type_vals[] = {
736 { TRAF_ST_UNKNOWN, "Unknown VC multiplexed traffic type" },
737 { TRAF_ST_VCMX_802_3_FCS, "802.3 FCS" },
738 { TRAF_ST_VCMX_802_4_FCS, "802.4 FCS" },
739 { TRAF_ST_VCMX_802_5_FCS, "802.5 FCS" },
740 { TRAF_ST_VCMX_FDDI_FCS, "FDDI FCS" },
741 { TRAF_ST_VCMX_802_6_FCS, "802.6 FCS" },
742 { TRAF_ST_VCMX_802_3, "802.3" },
743 { TRAF_ST_VCMX_802_4, "802.4" },
744 { TRAF_ST_VCMX_802_5, "802.5" },
745 { TRAF_ST_VCMX_FDDI, "FDDI" },
746 { TRAF_ST_VCMX_802_6, "802.6" },
747 { TRAF_ST_VCMX_FRAGMENTS, "Fragments" },
748 { TRAF_ST_VCMX_BPDU, "BPDU" },
752 /* Traffic subtypes for LANE traffic */
753 static const value_string lane_type_vals[] = {
754 { TRAF_ST_UNKNOWN, "Unknown LANE traffic type" },
755 { TRAF_ST_LANE_LE_CTRL, "LE Control" },
756 { TRAF_ST_LANE_802_3, "802.3" },
757 { TRAF_ST_LANE_802_5, "802.5" },
758 { TRAF_ST_LANE_802_3_MC, "802.3 multicast" },
759 { TRAF_ST_LANE_802_5_MC, "802.5 multicast" },
763 /* Traffic subtypes for Ipsilon traffic */
764 static const value_string ipsilon_type_vals[] = {
765 { TRAF_ST_UNKNOWN, "Unknown Ipsilon traffic type" },
766 { TRAF_ST_IPSILON_FT0, "Flow type 0" },
767 { TRAF_ST_IPSILON_FT1, "Flow type 1" },
768 { TRAF_ST_IPSILON_FT2, "Flow type 2" },
773 capture_atm(const union wtap_pseudo_header *pseudo_header, const guchar *pd,
774 int len, packet_counts *ld)
776 if (pseudo_header->atm.aal == AAL_5) {
777 switch (pseudo_header->atm.type) {
780 /* Dissect as WTAP_ENCAP_ATM_RFC1483 */
781 /* The ATM iptrace capture that we have shows LLC at this point,
782 * so that's what I'm calling */
783 capture_llc(pd, 0, len, ld);
787 capture_lane(pseudo_header, pd, len, ld);
799 * Charles Michael Heard's CRC-32 code, from
801 * http://www.cell-relay.com/cell-relay/publications/software/CRC/32bitCRC.c.html
803 * with the CRC table initialized with values computed by
804 * his "gen_crc_table()" routine, rather than by calling that routine
805 * at run time, and with various data type cleanups.
808 /* crc32h.c -- package to compute 32-bit CRC one byte at a time using */
809 /* the high-bit first (Big-Endian) bit ordering convention */
812 /* gen_crc_table() -- generates a 256-word table containing all CRC */
813 /* remainders for every possible 8-bit byte. It */
814 /* must be executed (once) before any CRC updates. */
816 /* unsigned update_crc(crc_accum, data_blk_ptr, data_blk_size) */
817 /* unsigned crc_accum; char *data_blk_ptr; int data_blk_size; */
818 /* Returns the updated value of the CRC accumulator after */
819 /* processing each byte in the addressed block of data. */
821 /* It is assumed that an unsigned long is at least 32 bits wide and */
822 /* that the predefined type char occupies one 8-bit byte of storage. */
824 /* The generator polynomial used for this version of the package is */
825 /* 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 */
826 /* as specified in the Autodin/Ethernet/ADCCP protocol standards. */
827 /* Other degree 32 polynomials may be substituted by re-defining the */
828 /* symbol POLYNOMIAL below. Lower degree polynomials must first be */
829 /* multiplied by an appropriate power of x. The representation used */
830 /* is that the coefficient of x^0 is stored in the LSB of the 32-bit */
831 /* word and the coefficient of x^31 is stored in the most significant */
832 /* bit. The CRC is to be appended to the data most significant byte */
833 /* first. For those protocols in which bytes are transmitted MSB */
834 /* first and in the same order as they are encountered in the block */
835 /* this convention results in the CRC remainder being transmitted with */
836 /* the coefficient of x^31 first and with that of x^0 last (just as */
837 /* would be done by a hardware shift register mechanization). */
839 /* The table lookup technique was adapted from the algorithm described */
840 /* by Avram Perez, Byte-wise CRC Calculations, IEEE Micro 3, 40 (1983).*/
842 static const guint32 crc_table[256] = {
843 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
844 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
845 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
846 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
847 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,
848 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
849 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011,
850 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
851 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
852 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
853 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,
854 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
855 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49,
856 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
857 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
858 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
859 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,
860 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
861 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
862 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
863 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
864 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
865 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,
866 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
867 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e,
868 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
869 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
870 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
871 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
872 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
873 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686,
874 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
875 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
876 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
877 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,
878 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
879 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47,
880 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
881 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
882 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
883 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,
884 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
885 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f,
886 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
887 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
888 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
889 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,
890 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
891 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
892 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
893 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
894 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
895 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
896 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
897 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,
898 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
899 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
900 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
901 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
902 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
903 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,
904 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
905 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
906 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4,
910 update_crc(guint32 crc_accum, const guint8 *data_blk_ptr, int data_blk_size)
914 /* update the CRC on the data block one byte at a time */
915 for (j = 0; j < data_blk_size; j++) {
916 i = ( (int) ( crc_accum >> 24) ^ *data_blk_ptr++ ) & 0xff;
917 crc_accum = ( crc_accum << 8 ) ^ crc_table[i];
923 dissect_reassembled_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
925 proto_tree *atm_tree, gboolean truncated)
927 guint length, reported_length;
935 * ATM dissector is used as "sub-dissector" for ATM pseudowires.
936 * In such cases, pinfo->private_data is used to pass info from/to
937 * PW dissector to ATM dissector. For decoding normal ATM traffic
938 * private_data should be NULL.
940 gboolean pseudowire_mode = (NULL != pinfo->private_data);
943 * This is reassembled traffic, so the cell headers are missing;
944 * show the traffic type for AAL5 traffic, and the VPI and VCI,
945 * from the pseudo-header.
947 if (pinfo->pseudo_header->atm.aal == AAL_5) {
948 proto_tree_add_text(atm_tree, tvb, 0, 0, "Traffic type: %s",
949 val_to_str(pinfo->pseudo_header->atm.type, aal5_hltype_vals,
950 "Unknown AAL5 traffic type (%u)"));
951 switch (pinfo->pseudo_header->atm.type) {
954 proto_tree_add_text(atm_tree, tvb, 0, 0, "VC multiplexed traffic type: %s",
955 val_to_str(pinfo->pseudo_header->atm.subtype,
956 vcmx_type_vals, "Unknown VCMX traffic type (%u)"));
960 proto_tree_add_text(atm_tree, tvb, 0, 0, "LANE traffic type: %s",
961 val_to_str(pinfo->pseudo_header->atm.subtype,
962 lane_type_vals, "Unknown LANE traffic type (%u)"));
966 proto_tree_add_text(atm_tree, tvb, 0, 0, "Ipsilon traffic type: %s",
967 val_to_str(pinfo->pseudo_header->atm.subtype,
968 ipsilon_type_vals, "Unknown Ipsilon traffic type (%u)"));
972 if (!pseudowire_mode) {
973 proto_tree_add_uint(atm_tree, hf_atm_vpi, tvb, 0, 0,
974 pinfo->pseudo_header->atm.vpi);
975 proto_tree_add_uint(atm_tree, hf_atm_vci, tvb, 0, 0,
976 pinfo->pseudo_header->atm.vci);
978 /* Also show vpi/vci in info column */
979 col_append_fstr(pinfo->cinfo, COL_INFO, " VPI=%u, VCI=%u",
980 pinfo->pseudo_header->atm.vpi,
981 pinfo->pseudo_header->atm.vci);
987 * The packet data does not include stuff such as the AAL5
990 if (pinfo->pseudo_header->atm.cells != 0) {
992 * If the cell count is 0, assume it means we don't know how
995 * XXX - also assume it means we don't know what was in the AAL5
996 * trailer. We may, however, find some capture program that can
997 * give us the AAL5 trailer information but not the cell count,
998 * in which case we need some other way of indicating whether we
999 * have the AAL5 trailer information.
1002 proto_tree_add_text(atm_tree, tvb, 0, 0, "Cells: %u",
1003 pinfo->pseudo_header->atm.cells);
1004 proto_tree_add_text(atm_tree, tvb, 0, 0, "AAL5 UU: 0x%02x",
1005 pinfo->pseudo_header->atm.aal5t_u2u >> 8);
1006 proto_tree_add_text(atm_tree, tvb, 0, 0, "AAL5 CPI: 0x%02x",
1007 pinfo->pseudo_header->atm.aal5t_u2u & 0xFF);
1008 proto_tree_add_text(atm_tree, tvb, 0, 0, "AAL5 len: %u",
1009 pinfo->pseudo_header->atm.aal5t_len);
1010 proto_tree_add_text(atm_tree, tvb, 0, 0, "AAL5 CRC: 0x%08X",
1011 pinfo->pseudo_header->atm.aal5t_chksum);
1016 * The packet data includes stuff such as the AAL5 trailer, if
1017 * it wasn't cut off by the snapshot length.
1018 * Decode the trailer, if present, and then chop it off.
1020 length = tvb_length(tvb);
1021 reported_length = tvb_reported_length(tvb);
1022 if ((reported_length % 48) == 0) {
1024 * Reported length is a multiple of 48, so we can presumably
1025 * divide it by 48 to get the number of cells.
1027 proto_tree_add_text(atm_tree, tvb, 0, 0, "Cells: %u",
1028 reported_length/48);
1030 if ((pinfo->pseudo_header->atm.aal == AAL_5 ||
1031 pinfo->pseudo_header->atm.aal == AAL_SIGNALLING) &&
1032 length >= reported_length) {
1034 * XXX - what if the packet is truncated? Can that happen?
1035 * What if you capture with Windows Sniffer on an ATM link
1036 * and tell it not to save the entire packet? What happens
1039 aal5_length = tvb_get_ntohs(tvb, length - 6);
1042 * Check for sanity in the AAL5 length. It must be > 0
1043 * and must be less than the amount of space left after
1044 * we remove the trailer.
1046 * If it's not sane, assume we don't have a trailer.
1048 if (aal5_length > 0 && aal5_length <= length - 8) {
1050 * How much padding is there?
1052 pad_length = length - aal5_length - 8;
1055 * There is no reason for more than 47 bytes of padding.
1056 * The most padding you can have would be 7 bytes at the
1057 * end of the next-to-last cell (8 bytes after the end of
1058 * the data means you can fit the trailer in that cell),
1059 * plus 40 bytes in the last cell (with the last 8 bytes
1062 * If there's more than 47 bytes of padding, assume we don't
1065 if (pad_length <= 47) {
1067 if (pad_length > 0) {
1068 proto_tree_add_text(atm_tree, tvb, aal5_length, pad_length,
1071 proto_tree_add_text(atm_tree, tvb, length - 8, 1, "AAL5 UU: 0x%02x",
1072 tvb_get_guint8(tvb, length - 8));
1073 proto_tree_add_text(atm_tree, tvb, length - 7, 1, "AAL5 CPI: 0x%02x",
1074 tvb_get_guint8(tvb, length - 7));
1075 proto_tree_add_text(atm_tree, tvb, length - 6, 2, "AAL5 len: %u",
1077 crc = tvb_get_ntohl(tvb, length - 4);
1078 calc_crc = update_crc(0xFFFFFFFF, tvb_get_ptr(tvb, 0, length),
1080 proto_tree_add_text(atm_tree, tvb, length - 4, 4,
1081 "AAL5 CRC: 0x%08X (%s)", crc,
1082 (calc_crc == 0xC704DD7B) ? "correct" : "incorrect");
1084 next_tvb = tvb_new_subset(tvb, 0, aal5_length, aal5_length);
1090 switch (pinfo->pseudo_header->atm.aal) {
1092 case AAL_SIGNALLING:
1093 call_dissector(sscop_handle, next_tvb, pinfo, tree);
1097 switch (pinfo->pseudo_header->atm.type) {
1100 call_dissector(fr_handle, next_tvb, pinfo, tree);
1104 call_dissector(llc_handle, next_tvb, pinfo, tree);
1108 call_dissector(lane_handle, next_tvb, pinfo, tree);
1112 call_dissector(ilmi_handle, next_tvb, pinfo, tree);
1116 call_dissector(gprs_ns_handle, next_tvb, pinfo, tree);
1121 gboolean decoded = FALSE;
1123 if (tvb_length(next_tvb) > 7) /* sizeof(octet) */
1126 tvb_memcpy(next_tvb, octet, 0, sizeof(octet));
1129 if (octet[0] == 0xaa
1131 && octet[2] == 0x03) /* LLC SNAP as per RFC2684 */
1133 call_dissector(llc_handle, next_tvb, pinfo, tree);
1135 else if ((pntohs(octet) & 0xff) == PPP_IP)
1137 call_dissector(ppp_handle, next_tvb, pinfo, tree);
1139 else if (pntohs(octet) == 0x00)
1141 /* assume vc muxed bridged ethernet */
1142 proto_tree_add_text(tree, tvb, 0, 2, "Pad: 0x0000");
1143 next_tvb = tvb_new_subset_remaining(tvb, 2);
1144 call_dissector(eth_handle, next_tvb, pinfo, tree);
1146 else if (octet[2] == 0x03 && /* NLPID */
1147 ((octet[3] == 0xcc || /* IPv4 */
1148 octet[3] == 0x8e) || /* IPv6 */
1149 (octet[3] == 0x00 && /* Eth */
1150 octet[4] == 0x80))) /* Eth */
1152 /* assume network interworking with FR 2 byte header */
1153 call_dissector(fr_handle, next_tvb, pinfo, tree);
1155 else if (octet[4] == 0x03 && /* NLPID */
1156 ((octet[5] == 0xcc || /* IPv4 */
1157 octet[5] == 0x8e) || /* IPv6 */
1158 (octet[5] == 0x00 && /* Eth */
1159 octet[6] == 0x80))) /* Eth */
1161 /* assume network interworking with FR 4 byte header */
1162 call_dissector(fr_handle, next_tvb, pinfo, tree);
1164 else if (((octet[0] & 0xf0)== 0x40) ||
1165 ((octet[0] & 0xf0) == 0x60))
1167 call_dissector(ip_handle, next_tvb, pinfo, tree);
1175 if (tree && !decoded) {
1176 /* Dump it as raw data. */
1177 call_dissector(data_handle, next_tvb, pinfo, tree);
1185 proto_tree_add_uint(atm_tree, hf_atm_cid, tvb, 0, 0,
1186 pinfo->pseudo_header->atm.aal2_cid);
1187 proto_item_append_text(atm_ti, " (vpi=%u vci=%u cid=%u)",
1188 pinfo->pseudo_header->atm.vpi,
1189 pinfo->pseudo_header->atm.vci,
1190 pinfo->pseudo_header->atm.aal2_cid);
1192 if (pinfo->pseudo_header->atm.flags & ATM_AAL2_NOPHDR) {
1195 /* Skip first 4 bytes of message
1199 Ignoring for now... */
1200 next_tvb = tvb_new_subset_remaining(tvb, 4);
1203 type = pinfo->pseudo_header->atm.type;
1204 if (type == TRAF_UNKNOWN) {
1205 type = unknown_aal2_type;
1209 call_dissector(fp_handle, next_tvb, pinfo, tree);
1214 /* Dump it as raw data. */
1215 call_dissector(data_handle, next_tvb, pinfo, tree);
1223 /* Dump it as raw data. */
1224 call_dissector(data_handle, next_tvb, pinfo, tree);
1231 * Charles Michael Heard's HEC code, from
1233 * http://www.cell-relay.com/cell-relay/publications/software/CRC/32bitCRC.tutorial.html
1235 * with the syndrome and error position tables initialized with values
1236 * computed by his "gen_syndrome_table()" and "gen_err_posn_table()" routines,
1237 * rather than by calling those routines at run time, and with various data
1238 * type cleanups and changes not to correct the header if a correctible
1239 * error was detected.
1241 #define COSET_LEADER 0x055 /* x^6 + x^4 + x^2 + 1 */
1243 static const guint8 syndrome_table[256] = {
1244 0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15,
1245 0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d,
1246 0x70, 0x77, 0x7e, 0x79, 0x6c, 0x6b, 0x62, 0x65,
1247 0x48, 0x4f, 0x46, 0x41, 0x54, 0x53, 0x5a, 0x5d,
1248 0xe0, 0xe7, 0xee, 0xe9, 0xfc, 0xfb, 0xf2, 0xf5,
1249 0xd8, 0xdf, 0xd6, 0xd1, 0xc4, 0xc3, 0xca, 0xcd,
1250 0x90, 0x97, 0x9e, 0x99, 0x8c, 0x8b, 0x82, 0x85,
1251 0xa8, 0xaf, 0xa6, 0xa1, 0xb4, 0xb3, 0xba, 0xbd,
1252 0xc7, 0xc0, 0xc9, 0xce, 0xdb, 0xdc, 0xd5, 0xd2,
1253 0xff, 0xf8, 0xf1, 0xf6, 0xe3, 0xe4, 0xed, 0xea,
1254 0xb7, 0xb0, 0xb9, 0xbe, 0xab, 0xac, 0xa5, 0xa2,
1255 0x8f, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9d, 0x9a,
1256 0x27, 0x20, 0x29, 0x2e, 0x3b, 0x3c, 0x35, 0x32,
1257 0x1f, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0d, 0x0a,
1258 0x57, 0x50, 0x59, 0x5e, 0x4b, 0x4c, 0x45, 0x42,
1259 0x6f, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7d, 0x7a,
1260 0x89, 0x8e, 0x87, 0x80, 0x95, 0x92, 0x9b, 0x9c,
1261 0xb1, 0xb6, 0xbf, 0xb8, 0xad, 0xaa, 0xa3, 0xa4,
1262 0xf9, 0xfe, 0xf7, 0xf0, 0xe5, 0xe2, 0xeb, 0xec,
1263 0xc1, 0xc6, 0xcf, 0xc8, 0xdd, 0xda, 0xd3, 0xd4,
1264 0x69, 0x6e, 0x67, 0x60, 0x75, 0x72, 0x7b, 0x7c,
1265 0x51, 0x56, 0x5f, 0x58, 0x4d, 0x4a, 0x43, 0x44,
1266 0x19, 0x1e, 0x17, 0x10, 0x05, 0x02, 0x0b, 0x0c,
1267 0x21, 0x26, 0x2f, 0x28, 0x3d, 0x3a, 0x33, 0x34,
1268 0x4e, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5c, 0x5b,
1269 0x76, 0x71, 0x78, 0x7f, 0x6a, 0x6d, 0x64, 0x63,
1270 0x3e, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2c, 0x2b,
1271 0x06, 0x01, 0x08, 0x0f, 0x1a, 0x1d, 0x14, 0x13,
1272 0xae, 0xa9, 0xa0, 0xa7, 0xb2, 0xb5, 0xbc, 0xbb,
1273 0x96, 0x91, 0x98, 0x9f, 0x8a, 0x8d, 0x84, 0x83,
1274 0xde, 0xd9, 0xd0, 0xd7, 0xc2, 0xc5, 0xcc, 0xcb,
1275 0xe6, 0xe1, 0xe8, 0xef, 0xfa, 0xfd, 0xf4, 0xf3,
1278 #define NO_ERROR_DETECTED -128
1279 #define UNCORRECTIBLE_ERROR 128
1281 static const int err_posn_table[256] = {
1282 NO_ERROR_DETECTED, 39,
1283 38, UNCORRECTIBLE_ERROR,
1284 37, UNCORRECTIBLE_ERROR,
1285 UNCORRECTIBLE_ERROR, 31,
1286 36, UNCORRECTIBLE_ERROR,
1287 UNCORRECTIBLE_ERROR, 8,
1288 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1289 30, UNCORRECTIBLE_ERROR,
1290 35, UNCORRECTIBLE_ERROR,
1291 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1292 UNCORRECTIBLE_ERROR, 23,
1293 7, UNCORRECTIBLE_ERROR,
1294 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1295 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1296 29, UNCORRECTIBLE_ERROR,
1297 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1298 34, UNCORRECTIBLE_ERROR,
1299 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1300 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1301 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1302 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1303 22, UNCORRECTIBLE_ERROR,
1304 6, UNCORRECTIBLE_ERROR,
1305 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1306 UNCORRECTIBLE_ERROR, 0,
1307 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1308 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1309 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1310 28, UNCORRECTIBLE_ERROR,
1311 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1312 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1313 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1314 33, UNCORRECTIBLE_ERROR,
1315 UNCORRECTIBLE_ERROR, 10,
1316 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1317 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1318 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1319 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1320 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1321 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1322 UNCORRECTIBLE_ERROR, 12,
1323 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1324 21, UNCORRECTIBLE_ERROR,
1325 UNCORRECTIBLE_ERROR, 19,
1326 5, UNCORRECTIBLE_ERROR,
1327 UNCORRECTIBLE_ERROR, 17,
1328 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1329 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1330 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1331 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1332 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1333 UNCORRECTIBLE_ERROR, 3,
1334 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1335 UNCORRECTIBLE_ERROR, 15,
1336 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1337 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1338 27, UNCORRECTIBLE_ERROR,
1339 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1340 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1341 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1342 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1343 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1344 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1345 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1346 32, UNCORRECTIBLE_ERROR,
1347 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1348 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1349 9, UNCORRECTIBLE_ERROR,
1350 UNCORRECTIBLE_ERROR, 24,
1351 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1352 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1353 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1354 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1355 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1356 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1357 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1358 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1359 UNCORRECTIBLE_ERROR, 1,
1360 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1361 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1362 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1363 11, UNCORRECTIBLE_ERROR,
1364 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1365 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1366 20, UNCORRECTIBLE_ERROR,
1367 UNCORRECTIBLE_ERROR, 13,
1368 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1369 18, UNCORRECTIBLE_ERROR,
1370 4, UNCORRECTIBLE_ERROR,
1371 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1372 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1373 16, UNCORRECTIBLE_ERROR,
1374 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1375 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1376 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1377 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1378 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1379 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1380 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1381 UNCORRECTIBLE_ERROR, 25,
1382 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1383 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1384 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1385 2, UNCORRECTIBLE_ERROR,
1386 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1387 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1388 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1389 14, UNCORRECTIBLE_ERROR,
1390 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1391 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1392 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1393 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1394 26, 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,
1402 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1403 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1404 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1405 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1406 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1407 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1408 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1409 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1413 * Return an indication of whether there was an error in the cell header
1414 * and, if so, where the error was, if it was correctable.
1417 get_header_err(const guint8 *cell_header)
1419 register guint8 syndrome;
1420 register int i, err_posn;
1423 for (i = 0; i < 4; i++)
1424 syndrome = syndrome_table[syndrome ^ cell_header[i]];
1425 syndrome ^= cell_header[4] ^ COSET_LEADER;
1427 err_posn = err_posn_table [syndrome];
1430 return NO_ERROR_DETECTED;
1431 else if (err_posn < 40)
1434 return UNCORRECTIBLE_ERROR;
1437 const value_string atm_pt_vals[] = {
1438 { 0, "User data cell, congestion not experienced, SDU-type = 0" },
1439 { 1, "User data cell, congestion not experienced, SDU-type = 1" },
1440 { 2, "User data cell, congestion experienced, SDU-type = 0" },
1441 { 3, "User data cell, congestion experienced, SDU-type = 1" },
1442 { 4, "Segment OAM F5 flow related cell" },
1443 { 5, "End-to-end OAM F5 flow related cell" },
1444 { 6, "VC resource management cell" },
1449 * Charles Michael Heard's CRC-10 code, from
1451 * http://www.cell-relay.com/cell-relay/publications/software/CRC/crc10.html
1453 * with the CRC table initialized with values computed by
1454 * his "gen_byte_crc10_table()" routine, rather than by calling that
1455 * routine at run time, and with various data type cleanups.
1457 static const guint16 byte_crc10_table[256] = {
1458 0x0000, 0x0233, 0x0255, 0x0066, 0x0299, 0x00aa, 0x00cc, 0x02ff,
1459 0x0301, 0x0132, 0x0154, 0x0367, 0x0198, 0x03ab, 0x03cd, 0x01fe,
1460 0x0031, 0x0202, 0x0264, 0x0057, 0x02a8, 0x009b, 0x00fd, 0x02ce,
1461 0x0330, 0x0103, 0x0165, 0x0356, 0x01a9, 0x039a, 0x03fc, 0x01cf,
1462 0x0062, 0x0251, 0x0237, 0x0004, 0x02fb, 0x00c8, 0x00ae, 0x029d,
1463 0x0363, 0x0150, 0x0136, 0x0305, 0x01fa, 0x03c9, 0x03af, 0x019c,
1464 0x0053, 0x0260, 0x0206, 0x0035, 0x02ca, 0x00f9, 0x009f, 0x02ac,
1465 0x0352, 0x0161, 0x0107, 0x0334, 0x01cb, 0x03f8, 0x039e, 0x01ad,
1466 0x00c4, 0x02f7, 0x0291, 0x00a2, 0x025d, 0x006e, 0x0008, 0x023b,
1467 0x03c5, 0x01f6, 0x0190, 0x03a3, 0x015c, 0x036f, 0x0309, 0x013a,
1468 0x00f5, 0x02c6, 0x02a0, 0x0093, 0x026c, 0x005f, 0x0039, 0x020a,
1469 0x03f4, 0x01c7, 0x01a1, 0x0392, 0x016d, 0x035e, 0x0338, 0x010b,
1470 0x00a6, 0x0295, 0x02f3, 0x00c0, 0x023f, 0x000c, 0x006a, 0x0259,
1471 0x03a7, 0x0194, 0x01f2, 0x03c1, 0x013e, 0x030d, 0x036b, 0x0158,
1472 0x0097, 0x02a4, 0x02c2, 0x00f1, 0x020e, 0x003d, 0x005b, 0x0268,
1473 0x0396, 0x01a5, 0x01c3, 0x03f0, 0x010f, 0x033c, 0x035a, 0x0169,
1474 0x0188, 0x03bb, 0x03dd, 0x01ee, 0x0311, 0x0122, 0x0144, 0x0377,
1475 0x0289, 0x00ba, 0x00dc, 0x02ef, 0x0010, 0x0223, 0x0245, 0x0076,
1476 0x01b9, 0x038a, 0x03ec, 0x01df, 0x0320, 0x0113, 0x0175, 0x0346,
1477 0x02b8, 0x008b, 0x00ed, 0x02de, 0x0021, 0x0212, 0x0274, 0x0047,
1478 0x01ea, 0x03d9, 0x03bf, 0x018c, 0x0373, 0x0140, 0x0126, 0x0315,
1479 0x02eb, 0x00d8, 0x00be, 0x028d, 0x0072, 0x0241, 0x0227, 0x0014,
1480 0x01db, 0x03e8, 0x038e, 0x01bd, 0x0342, 0x0171, 0x0117, 0x0324,
1481 0x02da, 0x00e9, 0x008f, 0x02bc, 0x0043, 0x0270, 0x0216, 0x0025,
1482 0x014c, 0x037f, 0x0319, 0x012a, 0x03d5, 0x01e6, 0x0180, 0x03b3,
1483 0x024d, 0x007e, 0x0018, 0x022b, 0x00d4, 0x02e7, 0x0281, 0x00b2,
1484 0x017d, 0x034e, 0x0328, 0x011b, 0x03e4, 0x01d7, 0x01b1, 0x0382,
1485 0x027c, 0x004f, 0x0029, 0x021a, 0x00e5, 0x02d6, 0x02b0, 0x0083,
1486 0x012e, 0x031d, 0x037b, 0x0148, 0x03b7, 0x0184, 0x01e2, 0x03d1,
1487 0x022f, 0x001c, 0x007a, 0x0249, 0x00b6, 0x0285, 0x02e3, 0x00d0,
1488 0x011f, 0x032c, 0x034a, 0x0179, 0x0386, 0x01b5, 0x01d3, 0x03e0,
1489 0x021e, 0x002d, 0x004b, 0x0278, 0x0087, 0x02b4, 0x02d2, 0x00e1,
1492 /* update the data block's CRC-10 remainder one byte at a time */
1494 update_crc10_by_bytes(guint16 crc10_accum, const guint8 *data_blk_ptr,
1499 for (i = 0; i < data_blk_size; i++) {
1500 crc10_accum = ((crc10_accum << 8) & 0x3ff)
1501 ^ byte_crc10_table[( crc10_accum >> 2) & 0xff]
1507 static const value_string st_vals[] = {
1515 #define OAM_TYPE_FM 1 /* Fault Management */
1516 #define OAM_TYPE_PM 2 /* Performance Management */
1517 #define OAM_TYPE_AD 8 /* Activation/Deactivation */
1519 static const value_string oam_type_vals[] = {
1520 { OAM_TYPE_FM, "Fault Management" },
1521 { OAM_TYPE_PM, "Performance Management" },
1522 { OAM_TYPE_AD, "Activation/Deactivation" },
1526 static const value_string ft_fm_vals[] = {
1527 { 0, "Alarm Indication Signal" },
1528 { 1, "Far End Receive Failure" },
1529 { 8, "OAM Cell Loopback" },
1530 { 4, "Continuity Check" },
1534 static const value_string ft_pm_vals[] = {
1535 { 0, "Forward Monitoring" },
1536 { 1, "Backward Reporting" },
1537 { 2, "Monitoring and Reporting" },
1541 static const value_string ft_ad_vals[] = {
1542 { 0, "Performance Monitoring" },
1543 { 1, "Continuity Check" },
1549 * Check for OAM cells.
1550 * OAM F4 is VCI 3 or 4 and PT 0X0.
1553 gboolean atm_is_oam_cell(const guint16 vci, const guint8 pt)
1555 return (((vci == 3 || vci == 4) && ((pt & 0x5) == 0))
1556 || ((pt & 0x6) == 0x4));
1561 dissect_atm_cell(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1562 proto_tree *atm_tree, guint aal, gboolean nni,
1563 gboolean crc_stripped)
1566 proto_tree *aal_tree;
1573 guint16 aal3_4_hdr, aal3_4_trlr;
1578 const pwatm_private_data_t * pwpd = pinfo->private_data;
1583 * FF: ITU-T I.361 (Section 2.2) defines the cell header format
1584 * and encoding at UNI reference point as:
1599 octet = tvb_get_guint8(tvb, 0);
1600 proto_tree_add_text(atm_tree, tvb, 0, 1, "GFC: 0x%x", octet >> 4);
1601 vpi = (octet & 0xF) << 4;
1602 octet = tvb_get_guint8(tvb, 1);
1604 proto_tree_add_uint(atm_tree, hf_atm_vpi, tvb, 0, 2, vpi);
1607 * FF: ITU-T I.361 (Section 2.3) defines the cell header format
1608 * and encoding at NNI reference point as:
1623 octet = tvb_get_guint8(tvb, 0);
1625 octet = tvb_get_guint8(tvb, 1);
1626 vpi |= (octet & 0xF0) >> 4;
1627 proto_tree_add_uint(atm_tree, hf_atm_vpi, tvb, 0, 2, vpi);
1630 vci = (octet & 0x0F) << 12;
1631 octet = tvb_get_guint8(tvb, 2);
1633 octet = tvb_get_guint8(tvb, 3);
1635 proto_tree_add_uint(atm_tree, hf_atm_vci, tvb, 1, 3, vci);
1636 pt = (octet >> 1) & 0x7;
1637 proto_tree_add_text(atm_tree, tvb, 3, 1, "Payload Type: %s",
1638 val_to_str(pt, atm_pt_vals, "Unknown (%u)"));
1639 proto_tree_add_text(atm_tree, tvb, 3, 1, "Cell Loss Priority: %s",
1640 (octet & 0x01) ? "Low priority" : "High priority");
1642 if (!crc_stripped) {
1644 * FF: parse the Header Error Check (HEC).
1646 ti = proto_tree_add_text(atm_tree, tvb, 4, 1,
1647 "Header Error Check: 0x%02x",
1648 tvb_get_guint8(tvb, 4));
1649 err = get_header_err(tvb_get_ptr(tvb, 0, 5));
1650 if (err == NO_ERROR_DETECTED)
1651 proto_item_append_text(ti, " (correct)");
1652 else if (err == UNCORRECTIBLE_ERROR)
1653 proto_item_append_text(ti, " (uncorrectable error)");
1655 proto_item_append_text(ti, " (error in bit %d)", err);
1659 * FF: in some encapsulation modes (e.g. RFC 4717, ATM N-to-One
1660 * Cell Mode) the Header Error Check (HEC) field is stripped.
1661 * So we do nothing here.
1668 offset = 0; /* For PWs. Header is decoded by PW dissector.*/
1669 pwpd = pinfo->private_data;
1676 * Check for OAM cells.
1677 * XXX - do this for all AAL values, overriding whatever information
1678 * Wiretap got from the file?
1680 if (aal == AAL_USER) {
1681 if (atm_is_oam_cell(vci,pt)) {
1689 col_set_str(pinfo->cinfo, COL_PROTOCOL, "AAL1");
1690 col_clear(pinfo->cinfo, COL_INFO);
1691 ti = proto_tree_add_item(tree, proto_aal1, tvb, offset, -1, ENC_NA);
1692 aal_tree = proto_item_add_subtree(ti, ett_aal1);
1693 octet = tvb_get_guint8(tvb, offset);
1694 proto_tree_add_text(aal_tree, tvb, offset, 1, "CSI: %u", octet >> 7);
1695 proto_tree_add_text(aal_tree, tvb, offset, 1, "Sequence Count: %u",
1696 (octet >> 4) & 0x7);
1697 col_add_fstr(pinfo->cinfo, COL_INFO, "Sequence count = %u",
1698 (octet >> 4) & 0x7);
1699 proto_tree_add_text(aal_tree, tvb, offset, 1, "CRC: 0x%x",
1700 (octet >> 1) & 0x7);
1701 proto_tree_add_text(aal_tree, tvb, offset, 1, "Parity: %u",
1705 proto_tree_add_text(aal_tree, tvb, offset, 47, "Payload");
1710 * XXX - or should this be the CS PDU?
1712 col_set_str(pinfo->cinfo, COL_PROTOCOL, "AAL3/4");
1713 col_clear(pinfo->cinfo, COL_INFO);
1714 ti = proto_tree_add_item(tree, proto_aal3_4, tvb, offset, -1, ENC_NA);
1715 aal_tree = proto_item_add_subtree(ti, ett_aal3_4);
1716 aal3_4_hdr = tvb_get_ntohs(tvb, offset);
1717 col_add_fstr(pinfo->cinfo, COL_INFO, "%s, sequence number = %u",
1718 val_to_str(aal3_4_hdr >> 14, st_vals, "Unknown (%u)"),
1719 (aal3_4_hdr >> 10) & 0xF);
1720 proto_tree_add_text(aal_tree, tvb, offset, 2, "Segment Type: %s",
1721 val_to_str(aal3_4_hdr >> 14, st_vals, "Unknown (%u)"));
1722 proto_tree_add_text(aal_tree, tvb, offset, 2, "Sequence Number: %u",
1723 (aal3_4_hdr >> 10) & 0xF);
1724 proto_tree_add_text(aal_tree, tvb, offset, 2, "Multiplex ID: %u",
1725 aal3_4_hdr & 0x3FF);
1728 proto_tree_add_text(aal_tree, tvb, offset, 44, "Information");
1731 aal3_4_trlr = tvb_get_ntohs(tvb, offset);
1732 proto_tree_add_text(aal_tree, tvb, offset, 2, "Length Indicator: %u",
1733 (aal3_4_trlr >> 10) & 0x3F);
1734 length = tvb_length_remaining(tvb, 5);
1735 crc10 = update_crc10_by_bytes(0, tvb_get_ptr(tvb, 5, length),
1737 proto_tree_add_text(aal_tree, tvb, offset, 2, "CRC: 0x%03x (%s)",
1738 aal3_4_trlr & 0x3FF,
1739 (crc10 == 0) ? "correct" : "incorrect");
1743 if (NULL == pwpd || pwpd->enable_fill_columns_by_atm_dissector)
1745 col_set_str(pinfo->cinfo, COL_PROTOCOL, "OAM AAL");
1746 col_clear(pinfo->cinfo, COL_INFO);
1748 ti = proto_tree_add_item(tree, proto_oamaal, tvb, offset, -1, ENC_NA);
1749 aal_tree = proto_item_add_subtree(ti, ett_oamaal);
1750 octet = tvb_get_guint8(tvb, offset);
1751 if (NULL == pwpd || pwpd->enable_fill_columns_by_atm_dissector)
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_remaining(tvb, offset);
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 col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DCE");
1823 col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DTE");
1827 /* Traffic from DCE to DTE. */
1828 col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DTE");
1829 col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DCE");
1834 if (pinfo->pseudo_header->atm.aal == AAL_5) {
1835 col_add_fstr(pinfo->cinfo, COL_INFO, "AAL5 %s",
1836 val_to_str(pinfo->pseudo_header->atm.type, aal5_hltype_vals,
1837 "Unknown traffic type (%u)"));
1839 col_add_str(pinfo->cinfo, COL_INFO,
1840 val_to_str(pinfo->pseudo_header->atm.aal, aal_vals,
1841 "Unknown AAL (%u)"));
1845 atm_ti = proto_tree_add_item(tree, proto_atm, tvb, 0, -1, ENC_NA);
1846 atm_tree = proto_item_add_subtree(atm_ti, ett_atm);
1848 if (!pseudowire_mode) {
1849 switch (pinfo->pseudo_header->atm.channel) {
1852 /* Traffic from DTE to DCE. */
1853 proto_tree_add_text(atm_tree, tvb, 0, 0, "Channel: DTE->DCE");
1857 /* Traffic from DCE to DTE. */
1858 proto_tree_add_text(atm_tree, tvb, 0, 0, "Channel: DCE->DTE");
1862 /* Sniffers shouldn't provide anything other than 0 or 1. */
1863 proto_tree_add_text(atm_tree, tvb, 0, 0, "Channel: %u",
1864 pinfo->pseudo_header->atm.channel);
1869 proto_tree_add_uint_format_value(atm_tree, hf_atm_aal, tvb, 0, 0,
1870 pinfo->pseudo_header->atm.aal,
1872 val_to_str(pinfo->pseudo_header->atm.aal, aal_vals,
1873 "Unknown AAL (%u)"));
1875 if (pinfo->pseudo_header->atm.flags & ATM_RAW_CELL) {
1876 /* This is a single cell, with the cell header at the beginning. */
1877 if (pinfo->pseudo_header->atm.flags & ATM_NO_HEC) {
1878 proto_item_set_len(atm_ti, 4);
1880 proto_item_set_len(atm_ti, 5);
1882 dissect_atm_cell(tvb, pinfo, tree, atm_tree,
1883 pinfo->pseudo_header->atm.aal, FALSE,
1884 pinfo->pseudo_header->atm.flags & ATM_NO_HEC);
1886 /* This is a reassembled PDU. */
1887 dissect_reassembled_pdu(tvb, pinfo, tree, atm_tree, atm_ti, truncated);
1892 dissect_atm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1894 dissect_atm_common(tvb, pinfo, tree, TRUE);
1898 dissect_atm_untruncated(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1900 dissect_atm_common(tvb, pinfo, tree, ENC_BIG_ENDIAN);
1904 dissect_atm_oam_cell(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1906 proto_tree *atm_tree = NULL;
1907 proto_item *atm_ti = NULL;
1908 gboolean pseudowire_mode = (NULL != pinfo->private_data);
1910 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATM");
1912 if (!pseudowire_mode) {
1914 atm_ti = proto_tree_add_protocol_format(tree, proto_atm, tvb, 0, 0, "ATM");
1915 atm_tree = proto_item_add_subtree(atm_ti, ett_atm);
1919 dissect_atm_cell(tvb, pinfo, tree, atm_tree, AAL_OAMCELL, FALSE, ENC_BIG_ENDIAN);
1924 proto_register_atm(void)
1926 static hf_register_info hf[] = {
1928 { "AAL", "atm.aal", FT_UINT8, BASE_DEC, VALS(aal_vals), 0x0,
1932 { "VPI", "atm.vpi", FT_UINT8, BASE_DEC, NULL, 0x0,
1936 { "VCI", "atm.vci", FT_UINT16, BASE_DEC, NULL, 0x0,
1940 { "CID", "atm.cid", FT_UINT8, BASE_DEC, NULL, 0x0,
1944 static gint *ett[] = {
1951 &ett_atm_lane_lc_lan_dest,
1952 &ett_atm_lane_lc_lan_dest_rd,
1953 &ett_atm_lane_lc_flags,
1954 &ett_atm_lane_lc_tlv,
1957 static enum_val_t unknown_aal2_options[] = {
1958 { "raw", "Raw data", TRAF_UNKNOWN },
1959 { "umts_fp", "UMTS FP", TRAF_UMTS_FP },
1963 module_t *atm_module;
1965 proto_atm = proto_register_protocol("Asynchronous Transfer Mode", "ATM", "atm");
1966 proto_aal1 = proto_register_protocol("ATM AAL1", "AAL1", "aal1");
1967 proto_aal3_4 = proto_register_protocol("ATM AAL3/4", "AAL3/4", "aal3_4");
1968 proto_oamaal = proto_register_protocol("ATM OAM AAL", "OAM AAL", "oamaal");
1969 proto_register_field_array(proto_atm, hf, array_length(hf));
1970 proto_register_subtree_array(ett, array_length(ett));
1972 proto_ilmi = proto_register_protocol("ILMI", "ILMI", "ilmi");
1974 register_dissector("ilmi", dissect_ilmi, proto_ilmi);
1976 proto_atm_lane = proto_register_protocol("ATM LAN Emulation",
1977 "ATM LANE", "lane");
1979 register_dissector("lane", dissect_lane, proto_atm_lane);
1980 register_dissector("atm_untruncated", dissect_atm_untruncated, proto_atm);
1981 register_dissector("atm_truncated", dissect_atm, proto_atm);
1982 register_dissector("atm_oam_cell", dissect_atm_oam_cell, proto_oamaal);
1984 atm_module = prefs_register_protocol ( proto_atm, NULL );
1985 prefs_register_bool_preference ( atm_module, "dissect_lane_as_sscop", "Dissect LANE as SSCOP",
1986 "Autodection between LANE and SSCOP is hard. As default LANE is preferred",
1987 &dissect_lanesscop);
1988 prefs_register_enum_preference ( atm_module, "unknown_aal2_type",
1989 "Decode unknown AAL2 traffic as",
1990 "Type used to dissect unknown AAL2 traffic",
1991 &unknown_aal2_type, unknown_aal2_options, ENC_BIG_ENDIAN);
1996 proto_reg_handoff_atm(void)
1998 dissector_handle_t atm_handle, atm_untruncated_handle;
2001 * Get handles for the Ethernet, Token Ring, Frame Relay, LLC,
2002 * SSCOP, LANE, and ILMI dissectors.
2004 eth_withoutfcs_handle = find_dissector("eth_withoutfcs");
2005 tr_handle = find_dissector("tr");
2006 fr_handle = find_dissector("fr");
2007 llc_handle = find_dissector("llc");
2008 sscop_handle = find_dissector("sscop");
2009 lane_handle = find_dissector("lane");
2010 ilmi_handle = find_dissector("ilmi");
2011 ppp_handle = find_dissector("ppp");
2012 eth_handle = find_dissector("eth");
2013 ip_handle = find_dissector("ip");
2014 data_handle = find_dissector("data");
2015 fp_handle = find_dissector("fp");
2016 gprs_ns_handle = find_dissector("gprs_ns");
2018 atm_handle = create_dissector_handle(dissect_atm, proto_atm);
2019 dissector_add_uint("wtap_encap", WTAP_ENCAP_ATM_PDUS, atm_handle);
2021 atm_untruncated_handle = create_dissector_handle(dissect_atm_untruncated,
2023 dissector_add_uint("wtap_encap", WTAP_ENCAP_ATM_PDUS_UNTRUNCATED,
2024 atm_untruncated_handle);