MSWSP: add two more Property Sets
[wireshark-wip.git] / epan / dissectors / packet-atm.c
blobd1a6028ab9d6ca4b0335dc762f4d386b5e1dc35d
1 /* packet-atm.c
2 * Routines for ATM packet disassembly
4 * $Id$
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 #include "config.h"
27 #include <glib.h>
28 #include <epan/packet.h>
29 #include <wsutil/pint.h>
30 #include <epan/oui.h>
31 #include <epan/addr_resolv.h>
32 #include <epan/ppptypes.h>
34 #include "packet-atm.h"
35 #include "packet-snmp.h"
36 #include "packet-eth.h"
37 #include "packet-tr.h"
38 #include "packet-llc.h"
39 #include <epan/prefs.h>
40 #include "packet-pw-atm.h"
42 void proto_register_atm(void);
43 void proto_reg_handoff_atm(void);
45 static int proto_atm = -1;
46 static int hf_atm_aal = -1;
47 static int hf_atm_vpi = -1;
48 static int hf_atm_vci = -1;
49 static int hf_atm_cid = -1;
50 static int proto_atm_lane = -1;
51 static int proto_ilmi = -1;
52 static int proto_aal1 = -1;
53 static int proto_aal3_4 = -1;
54 static int proto_oamaal = -1;
56 static int hf_atm_le_client_client = -1;
57 static int hf_atm_lan_destination_tag = -1;
58 static int hf_atm_lan_destination_mac = -1;
59 static int hf_atm_le_control_tlv_type = -1;
60 static int hf_atm_le_control_tlv_length = -1;
61 static int hf_atm_lan_destination_route_desc = -1;
62 static int hf_atm_lan_destination_lan_id = -1;
63 static int hf_atm_lan_destination_bridge_num = -1;
64 static int hf_atm_source_atm = -1;
65 static int hf_atm_target_atm = -1;
66 static int hf_atm_le_configure_join_frame_lan_type = -1;
67 static int hf_atm_le_configure_join_frame_max_frame_size = -1;
68 static int hf_atm_le_configure_join_frame_num_tlvs = -1;
69 static int hf_atm_le_configure_join_frame_elan_name_size = -1;
70 static int hf_atm_le_configure_join_frame_elan_name = -1;
71 static int hf_atm_le_registration_frame_num_tlvs = -1;
72 static int hf_atm_le_arp_frame_num_tlvs = -1;
73 static int hf_atm_le_verify_frame_num_tlvs = -1;
74 static int hf_atm_le_control_marker = -1;
75 static int hf_atm_le_control_protocol = -1;
76 static int hf_atm_le_control_version = -1;
77 static int hf_atm_le_control_opcode = -1;
78 static int hf_atm_le_control_status = -1;
79 static int hf_atm_le_control_transaction_id = -1;
80 static int hf_atm_le_control_requester_lecid = -1;
81 static int hf_atm_le_control_flags = -1;
82 static int hf_atm_le_control_flag_v2_capable = -1;
83 static int hf_atm_le_control_flag_selective_multicast = -1;
84 static int hf_atm_le_control_flag_v2_required = -1;
85 static int hf_atm_le_control_flag_proxy = -1;
86 static int hf_atm_le_control_flag_exclude_explorer_frames = -1;
87 static int hf_atm_le_control_flag_address = -1;
88 static int hf_atm_le_control_topology_change = -1;
89 static int hf_atm_traffic_type = -1;
90 static int hf_atm_traffic_vcmx = -1;
91 static int hf_atm_traffic_lane = -1;
92 static int hf_atm_traffic_ipsilon = -1;
93 static int hf_atm_cells = -1;
94 static int hf_atm_aal5_uu = -1;
95 static int hf_atm_aal5_cpi = -1;
96 static int hf_atm_aal5_len = -1;
97 static int hf_atm_aal5_crc = -1;
98 static int hf_atm_payload_type = -1;
99 static int hf_atm_cell_loss_priority = -1;
100 static int hf_atm_header_error_check = -1;
101 static int hf_atm_channel = -1;
102 static int hf_atm_aa1_csi = -1;
103 static int hf_atm_aa1_seq_count = -1;
104 static int hf_atm_aa1_crc = -1;
105 static int hf_atm_aa1_parity = -1;
106 static int hf_atm_aa1_payload = -1;
107 static int hf_atm_aal3_4_seg_type = -1;
108 static int hf_atm_aal3_4_seq_num = -1;
109 static int hf_atm_aal3_4_multiplex_id = -1;
110 static int hf_atm_aal3_4_information = -1;
111 static int hf_atm_aal3_4_length_indicator = -1;
112 static int hf_atm_aal3_4_crc = -1;
113 static int hf_atm_aal_oamcell_type = -1;
114 static int hf_atm_aal_oamcell_type_fm = -1;
115 static int hf_atm_aal_oamcell_type_pm = -1;
116 static int hf_atm_aal_oamcell_type_ad = -1;
117 static int hf_atm_aal_oamcell_type_ft = -1;
118 static int hf_atm_aal_oamcell_func_spec = -1;
119 static int hf_atm_aal_oamcell_crc = -1;
121 static gint ett_atm = -1;
122 static gint ett_atm_lane = -1;
123 static gint ett_atm_lane_lc_lan_dest = -1;
124 static gint ett_atm_lane_lc_lan_dest_rd = -1;
125 static gint ett_atm_lane_lc_flags = -1;
126 static gint ett_atm_lane_lc_tlv = -1;
127 static gint ett_ilmi = -1;
128 static gint ett_aal1 = -1;
129 static gint ett_aal3_4 = -1;
130 static gint ett_oamaal = -1;
132 static dissector_handle_t atm_handle;
133 static dissector_handle_t atm_untruncated_handle;
135 static dissector_handle_t eth_withoutfcs_handle;
136 static dissector_handle_t tr_handle;
137 static dissector_handle_t fr_handle;
138 static dissector_handle_t llc_handle;
139 static dissector_handle_t sscop_handle;
140 static dissector_handle_t lane_handle;
141 static dissector_handle_t ilmi_handle;
142 static dissector_handle_t fp_handle;
143 static dissector_handle_t ppp_handle;
144 static dissector_handle_t eth_handle;
145 static dissector_handle_t ip_handle;
146 static dissector_handle_t data_handle;
147 static dissector_handle_t gprs_ns_handle;
149 static gboolean dissect_lanesscop = FALSE;
151 static gint unknown_aal2_type = TRAF_UNKNOWN;
154 * See
156 * http://www.atmforum.org/atmforum/specs/approved.html
158 * for a number of ATM Forum specifications, e.g. the LAN Emulation
159 * over ATM 1.0 spec, whence I got most of this.
162 /* LE Control opcodes */
163 #define LE_CONFIGURE_REQUEST 0x0001
164 #define LE_CONFIGURE_RESPONSE 0x0101
165 #define LE_JOIN_REQUEST 0x0002
166 #define LE_JOIN_RESPONSE 0x0102
167 #define READY_QUERY 0x0003
168 #define READY_IND 0x0103
169 #define LE_REGISTER_REQUEST 0x0004
170 #define LE_REGISTER_RESPONSE 0x0104
171 #define LE_UNREGISTER_REQUEST 0x0005
172 #define LE_UNREGISTER_RESPONSE 0x0105
173 #define LE_ARP_REQUEST 0x0006
174 #define LE_ARP_RESPONSE 0x0106
175 #define LE_FLUSH_REQUEST 0x0007
176 #define LE_FLUSH_RESPONSE 0x0107
177 #define LE_NARP_REQUEST 0x0008
178 #define LE_TOPOLOGY_REQUEST 0x0009
179 #define LE_VERIFY_REQUEST 0x000A
180 #define LE_VERIFY_RESPONSE 0x010A
182 static const value_string le_control_opcode_vals[] = {
183 { LE_CONFIGURE_REQUEST, "LE_CONFIGURE_REQUEST" },
184 { LE_CONFIGURE_RESPONSE, "LE_CONFIGURE_RESPONSE" },
185 { LE_JOIN_REQUEST, "LE_JOIN_REQUEST" },
186 { LE_JOIN_RESPONSE, "LE_JOIN_RESPONSE" },
187 { READY_QUERY, "READY_QUERY" },
188 { READY_IND, "READY_IND" },
189 { LE_REGISTER_REQUEST, "LE_REGISTER_REQUEST" },
190 { LE_REGISTER_RESPONSE, "LE_REGISTER_RESPONSE" },
191 { LE_UNREGISTER_REQUEST, "LE_UNREGISTER_REQUEST" },
192 { LE_UNREGISTER_RESPONSE, "LE_UNREGISTER_RESPONSE" },
193 { LE_ARP_REQUEST, "LE_ARP_REQUEST" },
194 { LE_ARP_RESPONSE, "LE_ARP_RESPONSE" },
195 { LE_FLUSH_REQUEST, "LE_FLUSH_REQUEST" },
196 { LE_FLUSH_RESPONSE, "LE_FLUSH_RESPONSE" },
197 { LE_NARP_REQUEST, "LE_NARP_REQUEST" },
198 { LE_TOPOLOGY_REQUEST, "LE_TOPOLOGY_REQUEST" },
199 { LE_VERIFY_REQUEST, "LE_VERIFY_REQUEST" },
200 { LE_VERIFY_RESPONSE, "LE_VERIFY_RESPONSE" },
201 { 0, NULL }
204 /* LE Control statuses */
205 static const value_string le_control_status_vals[] = {
206 { 0, "Success" },
207 { 1, "Version not supported" },
208 { 2, "Invalid request parameters" },
209 { 4, "Duplicate LAN destination registration" },
210 { 5, "Duplicate ATM address" },
211 { 6, "Insufficient resources to grant request" },
212 { 7, "Access denied" },
213 { 8, "Invalid REQUESTOR-ID" },
214 { 9, "Invalid LAN destination" },
215 { 10, "Invalid ATM address" },
216 { 20, "No configuration" },
217 { 21, "LE_CONFIGURE error" },
218 { 22, "Insufficient information" },
219 { 24, "TLV not found" },
220 { 0, NULL }
223 /* LE Control LAN destination tags */
224 #define TAG_NOT_PRESENT 0x0000
225 #define TAG_MAC_ADDRESS 0x0001
226 #define TAG_ROUTE_DESCRIPTOR 0x0002
228 static const value_string le_control_landest_tag_vals[] = {
229 { TAG_NOT_PRESENT, "Not present" },
230 { TAG_MAC_ADDRESS, "MAC address" },
231 { TAG_ROUTE_DESCRIPTOR, "Route descriptor" },
232 { 0, NULL }
235 /* LE Control LAN types */
236 #define LANT_UNSPEC 0x00
237 #define LANT_802_3 0x01
238 #define LANT_802_5 0x02
240 static const value_string le_control_lan_type_vals[] = {
241 { LANT_UNSPEC, "Unspecified" },
242 { LANT_802_3, "Ethernet/802.3" },
243 { LANT_802_5, "802.5" },
244 { 0, NULL }
247 static const value_string le_control_frame_size_vals[] = {
248 { 0x00, "Unspecified" },
249 { 0x01, "1516/1528/1580/1592" },
250 { 0x02, "4544/4556/1580/1592" },
251 { 0x03, "9234/9246" },
252 { 0x04, "18190/18202" },
253 { 0, NULL }
256 static const value_string atm_channel_vals[] = {
257 { 0, "DTE->DCE" },
258 { 1, "DCE->DTE" },
259 { 0, NULL }
262 static const true_false_string tfs_remote_local = { "Remote", "Local" };
263 static const true_false_string tfs_low_high_priority = { "Low priority", "High priority" };
266 static void
267 dissect_le_client(tvbuff_t *tvb, proto_tree *tree)
269 proto_item *ti;
270 proto_tree *lane_tree;
272 if (tree) {
273 ti = proto_tree_add_protocol_format(tree, proto_atm_lane, tvb, 0, 2, "ATM LANE");
274 lane_tree = proto_item_add_subtree(ti, ett_atm_lane);
276 proto_tree_add_item(lane_tree, hf_atm_le_client_client, tvb, 0, 2, ENC_BIG_ENDIAN );
280 static void
281 dissect_lan_destination(tvbuff_t *tvb, int offset, const char *type, proto_tree *tree)
283 proto_item *td;
284 proto_tree *dest_tree;
285 guint16 tag;
286 proto_tree *rd_tree;
288 td = proto_tree_add_text(tree, tvb, offset, 8, "%s LAN destination",
289 type);
290 dest_tree = proto_item_add_subtree(td, ett_atm_lane_lc_lan_dest);
291 tag = tvb_get_ntohs(tvb, offset);
292 proto_tree_add_item(dest_tree, hf_atm_lan_destination_tag, tvb, offset, 2, ENC_BIG_ENDIAN );
293 offset += 2;
295 switch (tag) {
297 case TAG_MAC_ADDRESS:
298 proto_tree_add_item(dest_tree, hf_atm_lan_destination_mac, tvb, offset, 6, ENC_NA);
299 break;
301 case TAG_ROUTE_DESCRIPTOR:
302 offset += 4;
303 proto_tree_add_item(dest_tree, hf_atm_lan_destination_route_desc, tvb, offset, 2, ENC_LITTLE_ENDIAN);
304 rd_tree = proto_item_add_subtree(td, ett_atm_lane_lc_lan_dest_rd);
305 proto_tree_add_item(rd_tree, hf_atm_lan_destination_lan_id, tvb, offset, 2, ENC_LITTLE_ENDIAN);
306 proto_tree_add_item(rd_tree, hf_atm_lan_destination_bridge_num, tvb, offset, 2, ENC_LITTLE_ENDIAN);
307 break;
312 * TLV values in LE Control frames.
314 #define TLV_TYPE(oui, ident) (((oui) << 8) | (ident))
316 #define LE_CONTROL_TIMEOUT TLV_TYPE(OUI_ATM_FORUM, 0x01)
317 #define LE_MAX_UNK_FRAME_COUNT TLV_TYPE(OUI_ATM_FORUM, 0x02)
318 #define LE_MAX_UNK_FRAME_TIME TLV_TYPE(OUI_ATM_FORUM, 0x03)
319 #define LE_VCC_TIMEOUT_PERIOD TLV_TYPE(OUI_ATM_FORUM, 0x04)
320 #define LE_MAX_RETRY_COUNT TLV_TYPE(OUI_ATM_FORUM, 0x05)
321 #define LE_AGING_TIME TLV_TYPE(OUI_ATM_FORUM, 0x06)
322 #define LE_FORWARD_DELAY_TIME TLV_TYPE(OUI_ATM_FORUM, 0x07)
323 #define LE_EXPECTED_ARP_RESPONSE_TIME TLV_TYPE(OUI_ATM_FORUM, 0x08)
324 #define LE_FLUSH_TIMEOUT TLV_TYPE(OUI_ATM_FORUM, 0x09)
325 #define LE_PATH_SWITCHING_DELAY TLV_TYPE(OUI_ATM_FORUM, 0x0A)
326 #define LE_LOCAL_SEGMENT_ID TLV_TYPE(OUI_ATM_FORUM, 0x0B)
327 #define LE_MCAST_SEND_VCC_TYPE TLV_TYPE(OUI_ATM_FORUM, 0x0C)
328 #define LE_MCAST_SEND_VCC_AVGRATE TLV_TYPE(OUI_ATM_FORUM, 0x0D)
329 #define LE_MCAST_SEND_VCC_PEAKRATE TLV_TYPE(OUI_ATM_FORUM, 0x0E)
330 #define LE_CONN_COMPLETION_TIMER TLV_TYPE(OUI_ATM_FORUM, 0x0F)
331 #define LE_CONFIG_FRAG_INFO TLV_TYPE(OUI_ATM_FORUM, 0x10)
332 #define LE_LAYER_3_ADDRESS TLV_TYPE(OUI_ATM_FORUM, 0x11)
333 #define LE_ELAN_ID TLV_TYPE(OUI_ATM_FORUM, 0x12)
334 #define LE_SERVICE_CATEGORY TLV_TYPE(OUI_ATM_FORUM, 0x13)
335 #define LE_LLC_MUXED_ATM_ADDRESS TLV_TYPE(OUI_ATM_FORUM, 0x2B)
336 #define LE_X5_ADJUSTMENT TLV_TYPE(OUI_ATM_FORUM, 0x2C)
337 #define LE_PREFERRED_LES TLV_TYPE(OUI_ATM_FORUM, 0x2D)
339 static const value_string le_tlv_type_vals[] = {
340 { LE_CONTROL_TIMEOUT, "Control Time-out" },
341 { LE_MAX_UNK_FRAME_COUNT, "Maximum Unknown Frame Count" },
342 { LE_MAX_UNK_FRAME_TIME, "Maximum Unknown Frame Time" },
343 { LE_VCC_TIMEOUT_PERIOD, "VCC Time-out" },
344 { LE_MAX_RETRY_COUNT, "Maximum Retry Count" },
345 { LE_AGING_TIME, "Aging Time" },
346 { LE_FORWARD_DELAY_TIME, "Forwarding Delay Time" },
347 { LE_EXPECTED_ARP_RESPONSE_TIME, "Expected LE_ARP Response Time" },
348 { LE_FLUSH_TIMEOUT, "Flush Time-out" },
349 { LE_PATH_SWITCHING_DELAY, "Path Switching Delay" },
350 { LE_LOCAL_SEGMENT_ID, "Local Segment ID" },
351 { LE_MCAST_SEND_VCC_TYPE, "Mcast Send VCC Type" },
352 { LE_MCAST_SEND_VCC_AVGRATE, "Mcast Send VCC AvgRate" },
353 { LE_MCAST_SEND_VCC_PEAKRATE, "Mcast Send VCC PeakRate" },
354 { LE_CONN_COMPLETION_TIMER, "Connection Completion Timer" },
355 { LE_CONFIG_FRAG_INFO, "Config Frag Info" },
356 { LE_LAYER_3_ADDRESS, "Layer 3 Address" },
357 { LE_ELAN_ID, "ELAN ID" },
358 { LE_SERVICE_CATEGORY, "Service Category" },
359 { LE_LLC_MUXED_ATM_ADDRESS, "LLC-muxed ATM Address" },
360 { LE_X5_ADJUSTMENT, "X5 Adjustment" },
361 { LE_PREFERRED_LES, "Preferred LES" },
362 { 0, NULL },
365 static void
366 dissect_le_control_tlvs(tvbuff_t *tvb, int offset, guint num_tlvs,
367 proto_tree *tree)
369 guint32 tlv_type;
370 guint8 tlv_length;
371 proto_item *ttlv;
372 proto_tree *tlv_tree;
374 while (num_tlvs != 0) {
375 tlv_type = tvb_get_ntohl(tvb, offset);
376 tlv_length = tvb_get_guint8(tvb, offset+4);
377 ttlv = proto_tree_add_text(tree, tvb, offset, 5+tlv_length, "TLV type: %s",
378 val_to_str(tlv_type, le_tlv_type_vals, "Unknown (0x%08x)"));
379 tlv_tree = proto_item_add_subtree(ttlv, ett_atm_lane_lc_tlv);
380 proto_tree_add_item(tlv_tree, hf_atm_le_control_tlv_type, tvb, offset, 4, ENC_BIG_ENDIAN);
381 proto_tree_add_item(tlv_tree, hf_atm_le_control_tlv_length, tvb, offset+4, 1, ENC_BIG_ENDIAN);
382 offset += 5+tlv_length;
383 num_tlvs--;
387 static void
388 dissect_le_configure_join_frame(tvbuff_t *tvb, int offset, proto_tree *tree)
390 guint8 num_tlvs;
391 guint8 name_size;
393 dissect_lan_destination(tvb, offset, "Source", tree);
394 offset += 8;
396 dissect_lan_destination(tvb, offset, "Target", tree);
397 offset += 8;
399 proto_tree_add_item(tree, hf_atm_source_atm, tvb, offset, 20, ENC_NA);
400 offset += 20;
402 proto_tree_add_item(tree, hf_atm_le_configure_join_frame_lan_type, tvb, offset, 1, ENC_NA);
403 offset += 1;
405 proto_tree_add_item(tree, hf_atm_le_configure_join_frame_max_frame_size, tvb, offset, 1, ENC_NA);
406 offset += 1;
408 num_tlvs = tvb_get_guint8(tvb, offset);
409 proto_tree_add_item(tree, hf_atm_le_configure_join_frame_num_tlvs, tvb, offset, 1, ENC_NA);
410 offset += 1;
412 name_size = tvb_get_guint8(tvb, offset);
413 proto_tree_add_item(tree, hf_atm_le_configure_join_frame_elan_name_size, tvb, offset, 1, ENC_NA);
414 offset += 1;
416 proto_tree_add_item(tree, hf_atm_target_atm, tvb, offset, 20, ENC_NA);
417 offset += 20;
419 if (name_size > 32)
420 name_size = 32;
421 if (name_size != 0) {
422 proto_tree_add_item(tree, hf_atm_le_configure_join_frame_elan_name, tvb, offset, name_size, ENC_NA);
424 offset += 32;
426 dissect_le_control_tlvs(tvb, offset, num_tlvs, tree);
429 static void
430 dissect_le_registration_frame(tvbuff_t *tvb, int offset, proto_tree *tree)
432 guint8 num_tlvs;
434 dissect_lan_destination(tvb, offset, "Source", tree);
435 offset += 8;
437 dissect_lan_destination(tvb, offset, "Target", tree);
438 offset += 8;
440 proto_tree_add_item(tree, hf_atm_source_atm, tvb, offset, 20, ENC_NA);
441 offset += 20;
443 /* Reserved */
444 offset += 2;
446 num_tlvs = tvb_get_guint8(tvb, offset);
447 proto_tree_add_item(tree, hf_atm_le_registration_frame_num_tlvs, tvb, offset, 1, ENC_NA);
448 offset += 1;
450 /* Reserved */
451 offset += 53;
453 dissect_le_control_tlvs(tvb, offset, num_tlvs, tree);
456 static void
457 dissect_le_arp_frame(tvbuff_t *tvb, int offset, proto_tree *tree)
459 guint8 num_tlvs;
461 dissect_lan_destination(tvb, offset, "Source", tree);
462 offset += 8;
464 dissect_lan_destination(tvb, offset, "Target", tree);
465 offset += 8;
467 proto_tree_add_item(tree, hf_atm_source_atm, tvb, offset, 20, ENC_NA);
468 offset += 20;
470 /* Reserved */
471 offset += 2;
473 num_tlvs = tvb_get_guint8(tvb, offset);
474 proto_tree_add_item(tree, hf_atm_le_arp_frame_num_tlvs, tvb, offset, 1, ENC_NA);
475 offset += 1;
477 /* Reserved */
478 offset += 1;
480 proto_tree_add_item(tree, hf_atm_target_atm, tvb, offset, 20, ENC_NA);
481 offset += 20;
483 /* Reserved */
484 offset += 32;
486 dissect_le_control_tlvs(tvb, offset, num_tlvs, tree);
489 static void
490 dissect_le_verify_frame(tvbuff_t *tvb, int offset, proto_tree *tree)
492 guint8 num_tlvs;
494 /* Reserved */
495 offset += 38;
497 num_tlvs = tvb_get_guint8(tvb, offset);
498 proto_tree_add_item(tree, hf_atm_le_verify_frame_num_tlvs, tvb, offset, 1, ENC_NA);
499 offset += 1;
501 /* Reserved */
502 offset += 1;
504 proto_tree_add_item(tree, hf_atm_target_atm, tvb, offset, 20, ENC_NA);
505 offset += 20;
507 /* Reserved */
508 offset += 32;
510 dissect_le_control_tlvs(tvb, offset, num_tlvs, tree);
513 static int
514 dissect_le_flush_frame(tvbuff_t *tvb, int offset, proto_tree *tree)
516 dissect_lan_destination(tvb, offset, "Source", tree);
517 offset += 8;
519 dissect_lan_destination(tvb, offset, "Target", tree);
520 offset += 8;
522 proto_tree_add_item(tree, hf_atm_source_atm, tvb, offset, 20, ENC_NA);
523 offset += 20;
525 /* Reserved */
526 offset += 4;
528 proto_tree_add_item(tree, hf_atm_target_atm, tvb, offset, 20, ENC_NA);
529 offset += 20;
531 /* Reserved */
532 offset += 32;
534 return offset;
537 static void
538 dissect_le_control(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
540 proto_item *ti;
541 proto_tree *lane_tree = NULL;
542 int offset = 0;
543 proto_item *tf;
544 proto_tree *flags_tree;
545 guint16 opcode;
547 col_set_str(pinfo->cinfo, COL_INFO, "LE Control");
549 if (tree) {
550 ti = proto_tree_add_protocol_format(tree, proto_atm_lane, tvb, offset, 108, "ATM LANE");
551 lane_tree = proto_item_add_subtree(ti, ett_atm_lane);
553 proto_tree_add_item(lane_tree, hf_atm_le_control_marker, tvb, offset, 2, ENC_BIG_ENDIAN );
555 offset += 2;
557 if (tree) {
558 proto_tree_add_item(lane_tree, hf_atm_le_control_protocol, tvb, offset, 1, ENC_BIG_ENDIAN );
561 offset += 1;
563 if (tree) {
564 proto_tree_add_item(lane_tree, hf_atm_le_control_version, tvb, offset, 1, ENC_BIG_ENDIAN );
566 offset += 1;
568 opcode = tvb_get_ntohs(tvb, offset);
569 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s",
570 val_to_str(opcode, le_control_opcode_vals,
571 "Unknown opcode (0x%04X)"));
573 if (tree) {
574 proto_tree_add_item(lane_tree, hf_atm_le_control_opcode, tvb, offset, 2, ENC_BIG_ENDIAN );
576 offset += 2;
578 if (opcode == READY_QUERY || opcode == READY_IND) {
579 /* There's nothing more in this packet. */
580 return;
583 if (tree) {
584 if (opcode & 0x0100) {
585 /* Response; decode status. */
586 proto_tree_add_item(lane_tree, hf_atm_le_control_status, tvb, offset, 2, ENC_BIG_ENDIAN );
588 offset += 2;
590 proto_tree_add_item(lane_tree, hf_atm_le_control_transaction_id, tvb, offset, 4, ENC_BIG_ENDIAN );
591 offset += 4;
593 proto_tree_add_item(lane_tree, hf_atm_le_control_requester_lecid, tvb, offset, 2, ENC_BIG_ENDIAN );
594 offset += 2;
596 tf = proto_tree_add_item(lane_tree, hf_atm_le_control_flags, tvb, offset, 2, ENC_BIG_ENDIAN );
597 flags_tree = proto_item_add_subtree(tf, ett_atm_lane_lc_flags);
599 switch (opcode) {
601 case LE_CONFIGURE_REQUEST:
602 case LE_CONFIGURE_RESPONSE:
603 proto_tree_add_item(flags_tree, hf_atm_le_control_flag_v2_capable, tvb, offset, 2, ENC_BIG_ENDIAN);
604 offset += 2;
605 dissect_le_configure_join_frame(tvb, offset, lane_tree);
606 break;
608 case LE_JOIN_REQUEST:
609 case LE_JOIN_RESPONSE:
610 proto_tree_add_item(flags_tree, hf_atm_le_control_flag_v2_capable, tvb, offset, 2, ENC_BIG_ENDIAN);
611 if (opcode == LE_JOIN_REQUEST) {
612 proto_tree_add_item(flags_tree, hf_atm_le_control_flag_selective_multicast, tvb, offset, 2, ENC_BIG_ENDIAN);
613 } else {
614 proto_tree_add_item(flags_tree, hf_atm_le_control_flag_v2_required, tvb, offset, 2, ENC_BIG_ENDIAN);
617 proto_tree_add_item(flags_tree, hf_atm_le_control_flag_proxy, tvb, offset, 2, ENC_BIG_ENDIAN);
618 proto_tree_add_item(flags_tree, hf_atm_le_control_flag_exclude_explorer_frames, tvb, offset, 2, ENC_BIG_ENDIAN);
620 offset += 2;
621 dissect_le_configure_join_frame(tvb, offset, lane_tree);
622 break;
624 case LE_REGISTER_REQUEST:
625 case LE_REGISTER_RESPONSE:
626 case LE_UNREGISTER_REQUEST:
627 case LE_UNREGISTER_RESPONSE:
628 offset += 2;
629 dissect_le_registration_frame(tvb, offset, lane_tree);
630 break;
632 case LE_ARP_REQUEST:
633 case LE_ARP_RESPONSE:
634 case LE_NARP_REQUEST:
635 if (opcode != LE_NARP_REQUEST) {
636 proto_tree_add_item(flags_tree, hf_atm_le_control_flag_address, tvb, offset, 2, ENC_BIG_ENDIAN);
638 offset += 2;
639 dissect_le_arp_frame(tvb, offset, lane_tree);
640 break;
642 case LE_TOPOLOGY_REQUEST:
643 proto_tree_add_item(flags_tree, hf_atm_le_control_topology_change, tvb, offset, 2, ENC_BIG_ENDIAN);
644 /* 92 reserved bytes */
645 break;
647 case LE_VERIFY_REQUEST:
648 case LE_VERIFY_RESPONSE:
649 offset += 2;
650 dissect_le_verify_frame(tvb, offset, lane_tree);
651 break;
653 case LE_FLUSH_REQUEST:
654 case LE_FLUSH_RESPONSE:
655 offset += 2;
656 dissect_le_flush_frame(tvb, offset, lane_tree);
657 break;
662 static void
663 capture_lane(const union wtap_pseudo_header *pseudo_header, const guchar *pd,
664 int len, packet_counts *ld)
666 /* Is it LE Control, 802.3, 802.5, or "none of the above"? */
667 switch (pseudo_header->atm.subtype) {
669 case TRAF_ST_LANE_802_3:
670 case TRAF_ST_LANE_802_3_MC:
671 /* Dissect as Ethernet */
672 capture_eth(pd, 2, len, ld);
673 break;
675 case TRAF_ST_LANE_802_5:
676 case TRAF_ST_LANE_802_5_MC:
677 /* Dissect as Token-Ring */
678 capture_tr(pd, 2, len, ld);
679 break;
681 default:
682 ld->other++;
683 break;
687 static void
688 dissect_lane(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
690 tvbuff_t *next_tvb;
691 tvbuff_t *next_tvb_le_client;
693 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATM LANE");
695 /* Is it LE Control, 802.3, 802.5, or "none of the above"? */
696 switch (pinfo->pseudo_header->atm.subtype) {
698 case TRAF_ST_LANE_LE_CTRL:
699 dissect_le_control(tvb, pinfo, tree);
700 break;
702 case TRAF_ST_LANE_802_3:
703 case TRAF_ST_LANE_802_3_MC:
704 col_set_str(pinfo->cinfo, COL_INFO, "LE Client - Ethernet/802.3");
705 dissect_le_client(tvb, tree);
707 /* Dissect as Ethernet */
708 next_tvb_le_client = tvb_new_subset_remaining(tvb, 2);
709 call_dissector(eth_withoutfcs_handle, next_tvb_le_client, pinfo, tree);
710 break;
712 case TRAF_ST_LANE_802_5:
713 case TRAF_ST_LANE_802_5_MC:
714 col_set_str(pinfo->cinfo, COL_INFO, "LE Client - 802.5");
715 dissect_le_client(tvb, tree);
717 /* Dissect as Token-Ring */
718 next_tvb_le_client = tvb_new_subset_remaining(tvb, 2);
719 call_dissector(tr_handle, next_tvb_le_client, pinfo, tree);
720 break;
722 default:
723 /* Dump it as raw data. */
724 col_set_str(pinfo->cinfo, COL_INFO, "Unknown LANE traffic type");
725 next_tvb = tvb_new_subset_remaining(tvb, 0);
726 call_dissector(data_handle,next_tvb, pinfo, tree);
727 break;
731 static void
732 dissect_ilmi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
734 dissect_snmp_pdu(tvb, 0, pinfo, tree, proto_ilmi, ett_ilmi, FALSE);
737 /* AAL types */
738 static const value_string aal_vals[] = {
739 { AAL_UNKNOWN, "Unknown AAL" },
740 { AAL_1, "AAL1" },
741 { AAL_2, "AAL2" },
742 { AAL_3_4, "AAL3/4" },
743 { AAL_5, "AAL5" },
744 { AAL_USER, "User AAL" },
745 { AAL_SIGNALLING, "Signalling AAL" },
746 { AAL_OAMCELL, "OAM cell" },
747 { 0, NULL }
750 /* AAL5 higher-level traffic types */
751 static const value_string aal5_hltype_vals[] = {
752 { TRAF_UNKNOWN, "Unknown traffic type" },
753 { TRAF_LLCMX, "LLC multiplexed" },
754 { TRAF_VCMX, "VC multiplexed" },
755 { TRAF_LANE, "LANE" },
756 { TRAF_ILMI, "ILMI" },
757 { TRAF_FR, "Frame Relay" },
758 { TRAF_SPANS, "FORE SPANS" },
759 { TRAF_IPSILON, "Ipsilon" },
760 { TRAF_GPRS_NS, "GPRS NS" },
761 { TRAF_SSCOP, "SSCOP" },
762 { 0, NULL }
765 /* Traffic subtypes for VC multiplexed traffic */
766 static const value_string vcmx_type_vals[] = {
767 { TRAF_ST_UNKNOWN, "Unknown VC multiplexed traffic type" },
768 { TRAF_ST_VCMX_802_3_FCS, "802.3 FCS" },
769 { TRAF_ST_VCMX_802_4_FCS, "802.4 FCS" },
770 { TRAF_ST_VCMX_802_5_FCS, "802.5 FCS" },
771 { TRAF_ST_VCMX_FDDI_FCS, "FDDI FCS" },
772 { TRAF_ST_VCMX_802_6_FCS, "802.6 FCS" },
773 { TRAF_ST_VCMX_802_3, "802.3" },
774 { TRAF_ST_VCMX_802_4, "802.4" },
775 { TRAF_ST_VCMX_802_5, "802.5" },
776 { TRAF_ST_VCMX_FDDI, "FDDI" },
777 { TRAF_ST_VCMX_802_6, "802.6" },
778 { TRAF_ST_VCMX_FRAGMENTS, "Fragments" },
779 { TRAF_ST_VCMX_BPDU, "BPDU" },
780 { 0, NULL }
783 /* Traffic subtypes for LANE traffic */
784 static const value_string lane_type_vals[] = {
785 { TRAF_ST_UNKNOWN, "Unknown LANE traffic type" },
786 { TRAF_ST_LANE_LE_CTRL, "LE Control" },
787 { TRAF_ST_LANE_802_3, "802.3" },
788 { TRAF_ST_LANE_802_5, "802.5" },
789 { TRAF_ST_LANE_802_3_MC, "802.3 multicast" },
790 { TRAF_ST_LANE_802_5_MC, "802.5 multicast" },
791 { 0, NULL }
794 /* Traffic subtypes for Ipsilon traffic */
795 static const value_string ipsilon_type_vals[] = {
796 { TRAF_ST_UNKNOWN, "Unknown Ipsilon traffic type" },
797 { TRAF_ST_IPSILON_FT0, "Flow type 0" },
798 { TRAF_ST_IPSILON_FT1, "Flow type 1" },
799 { TRAF_ST_IPSILON_FT2, "Flow type 2" },
800 { 0, NULL }
803 void
804 capture_atm(const union wtap_pseudo_header *pseudo_header, const guchar *pd,
805 int len, packet_counts *ld)
807 if (pseudo_header->atm.aal == AAL_5) {
808 switch (pseudo_header->atm.type) {
810 case TRAF_LLCMX:
811 /* Dissect as WTAP_ENCAP_ATM_RFC1483 */
812 /* The ATM iptrace capture that we have shows LLC at this point,
813 * so that's what I'm calling */
814 capture_llc(pd, 0, len, ld);
815 break;
817 case TRAF_LANE:
818 capture_lane(pseudo_header, pd, len, ld);
819 break;
821 default:
822 ld->other++;
823 break;
825 } else
826 ld->other++;
830 * Charles Michael Heard's CRC-32 code, from
832 * http://www.cell-relay.com/cell-relay/publications/software/CRC/32bitCRC.c.html
834 * with the CRC table initialized with values computed by
835 * his "gen_crc_table()" routine, rather than by calling that routine
836 * at run time, and with various data type cleanups.
839 /* crc32h.c -- package to compute 32-bit CRC one byte at a time using */
840 /* the high-bit first (Big-Endian) bit ordering convention */
841 /* */
842 /* Synopsis: */
843 /* gen_crc_table() -- generates a 256-word table containing all CRC */
844 /* remainders for every possible 8-bit byte. It */
845 /* must be executed (once) before any CRC updates. */
846 /* */
847 /* unsigned update_crc(crc_accum, data_blk_ptr, data_blk_size) */
848 /* unsigned crc_accum; char *data_blk_ptr; int data_blk_size; */
849 /* Returns the updated value of the CRC accumulator after */
850 /* processing each byte in the addressed block of data. */
851 /* */
852 /* It is assumed that an unsigned long is at least 32 bits wide and */
853 /* that the predefined type char occupies one 8-bit byte of storage. */
854 /* */
855 /* The generator polynomial used for this version of the package is */
856 /* 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 */
857 /* as specified in the Autodin/Ethernet/ADCCP protocol standards. */
858 /* Other degree 32 polynomials may be substituted by re-defining the */
859 /* symbol POLYNOMIAL below. Lower degree polynomials must first be */
860 /* multiplied by an appropriate power of x. The representation used */
861 /* is that the coefficient of x^0 is stored in the LSB of the 32-bit */
862 /* word and the coefficient of x^31 is stored in the most significant */
863 /* bit. The CRC is to be appended to the data most significant byte */
864 /* first. For those protocols in which bytes are transmitted MSB */
865 /* first and in the same order as they are encountered in the block */
866 /* this convention results in the CRC remainder being transmitted with */
867 /* the coefficient of x^31 first and with that of x^0 last (just as */
868 /* would be done by a hardware shift register mechanization). */
869 /* */
870 /* The table lookup technique was adapted from the algorithm described */
871 /* by Avram Perez, Byte-wise CRC Calculations, IEEE Micro 3, 40 (1983).*/
873 static const guint32 crc_table[256] = {
874 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
875 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
876 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
877 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
878 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,
879 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
880 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011,
881 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
882 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
883 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
884 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,
885 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
886 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49,
887 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
888 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
889 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
890 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,
891 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
892 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
893 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
894 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
895 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
896 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,
897 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
898 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e,
899 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
900 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
901 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
902 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
903 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
904 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686,
905 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
906 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
907 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
908 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,
909 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
910 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47,
911 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
912 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
913 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
914 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,
915 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
916 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f,
917 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
918 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
919 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
920 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,
921 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
922 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
923 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
924 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
925 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
926 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
927 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
928 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,
929 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
930 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
931 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
932 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
933 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
934 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,
935 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
936 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
937 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4,
940 static guint32
941 update_crc(guint32 crc_accum, const guint8 *data_blk_ptr, int data_blk_size)
943 register int i, j;
945 /* update the CRC on the data block one byte at a time */
946 for (j = 0; j < data_blk_size; j++) {
947 i = ( (int) ( crc_accum >> 24) ^ *data_blk_ptr++ ) & 0xff;
948 crc_accum = ( crc_accum << 8 ) ^ crc_table[i];
950 return crc_accum;
953 static void
954 dissect_reassembled_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
955 proto_item *atm_ti,
956 proto_tree *atm_tree, gboolean truncated, gboolean pseudowire_mode)
958 guint length, reported_length;
959 guint16 aal5_length;
960 int pad_length;
961 tvbuff_t *next_tvb;
962 guint32 crc;
963 guint32 calc_crc;
964 gint type;
967 * This is reassembled traffic, so the cell headers are missing;
968 * show the traffic type for AAL5 traffic, and the VPI and VCI,
969 * from the pseudo-header.
971 if (pinfo->pseudo_header->atm.aal == AAL_5) {
972 proto_tree_add_uint(atm_tree, hf_atm_traffic_type, tvb, 0, 0, pinfo->pseudo_header->atm.type);
974 switch (pinfo->pseudo_header->atm.type) {
976 case TRAF_VCMX:
977 proto_tree_add_uint(atm_tree, hf_atm_traffic_vcmx, tvb, 0, 0, pinfo->pseudo_header->atm.subtype);
978 break;
980 case TRAF_LANE:
981 proto_tree_add_uint(atm_tree, hf_atm_traffic_lane, tvb, 0, 0, pinfo->pseudo_header->atm.subtype);
982 break;
984 case TRAF_IPSILON:
985 proto_tree_add_uint(atm_tree, hf_atm_traffic_ipsilon, tvb, 0, 0, pinfo->pseudo_header->atm.subtype);
986 break;
989 if (!pseudowire_mode) {
990 proto_tree_add_uint(atm_tree, hf_atm_vpi, tvb, 0, 0,
991 pinfo->pseudo_header->atm.vpi);
992 proto_tree_add_uint(atm_tree, hf_atm_vci, tvb, 0, 0,
993 pinfo->pseudo_header->atm.vci);
995 /* Also show vpi/vci in info column */
996 col_append_fstr(pinfo->cinfo, COL_INFO, " VPI=%u, VCI=%u",
997 pinfo->pseudo_header->atm.vpi,
998 pinfo->pseudo_header->atm.vci);
1001 next_tvb = tvb;
1002 if (truncated) {
1004 * The packet data does not include stuff such as the AAL5
1005 * trailer.
1007 if (pinfo->pseudo_header->atm.cells != 0) {
1009 * If the cell count is 0, assume it means we don't know how
1010 * many cells it was.
1012 * XXX - also assume it means we don't know what was in the AAL5
1013 * trailer. We may, however, find some capture program that can
1014 * give us the AAL5 trailer information but not the cell count,
1015 * in which case we need some other way of indicating whether we
1016 * have the AAL5 trailer information.
1018 if (tree) {
1019 proto_tree_add_uint(atm_tree, hf_atm_cells, tvb, 0, 0, pinfo->pseudo_header->atm.cells);
1020 proto_tree_add_uint(atm_tree, hf_atm_aal5_uu, tvb, 0, 0, pinfo->pseudo_header->atm.aal5t_u2u >> 8);
1021 proto_tree_add_uint(atm_tree, hf_atm_aal5_cpi, tvb, 0, 0, pinfo->pseudo_header->atm.aal5t_u2u & 0xFF);
1022 proto_tree_add_uint(atm_tree, hf_atm_aal5_len, tvb, 0, 0, pinfo->pseudo_header->atm.aal5t_len);
1023 proto_tree_add_uint(atm_tree, hf_atm_aal5_crc, tvb, 0, 0, pinfo->pseudo_header->atm.aal5t_chksum);
1026 } else {
1028 * The packet data includes stuff such as the AAL5 trailer, if
1029 * it wasn't cut off by the snapshot length.
1030 * Decode the trailer, if present, and then chop it off.
1032 length = tvb_length(tvb);
1033 reported_length = tvb_reported_length(tvb);
1034 if ((reported_length % 48) == 0) {
1036 * Reported length is a multiple of 48, so we can presumably
1037 * divide it by 48 to get the number of cells.
1039 proto_tree_add_uint(atm_tree, hf_atm_cells, tvb, 0, 0, reported_length/48);
1041 if ((pinfo->pseudo_header->atm.aal == AAL_5 ||
1042 pinfo->pseudo_header->atm.aal == AAL_SIGNALLING) &&
1043 length >= reported_length) {
1045 * XXX - what if the packet is truncated? Can that happen?
1046 * What if you capture with Windows Sniffer on an ATM link
1047 * and tell it not to save the entire packet? What happens
1048 * to the trailer?
1050 aal5_length = tvb_get_ntohs(tvb, length - 6);
1053 * Check for sanity in the AAL5 length. It must be > 0
1054 * and must be less than the amount of space left after
1055 * we remove the trailer.
1057 * If it's not sane, assume we don't have a trailer.
1059 if (aal5_length > 0 && aal5_length <= length - 8) {
1061 * How much padding is there?
1063 pad_length = length - aal5_length - 8;
1066 * There is no reason for more than 47 bytes of padding.
1067 * The most padding you can have would be 7 bytes at the
1068 * end of the next-to-last cell (8 bytes after the end of
1069 * the data means you can fit the trailer in that cell),
1070 * plus 40 bytes in the last cell (with the last 8 bytes
1071 * being padding).
1073 * If there's more than 47 bytes of padding, assume we don't
1074 * have a trailer.
1076 if (pad_length <= 47) {
1077 if (tree) {
1078 proto_item *ti;
1080 if (pad_length > 0) {
1081 proto_tree_add_text(atm_tree, tvb, aal5_length, pad_length,
1082 "Padding");
1085 proto_tree_add_item(atm_tree, hf_atm_aal5_uu, tvb, length - 8, 1, ENC_BIG_ENDIAN);
1086 proto_tree_add_item(atm_tree, hf_atm_aal5_cpi, tvb, length - 7, 1, ENC_BIG_ENDIAN);
1087 proto_tree_add_item(atm_tree, hf_atm_aal5_len, tvb, length - 6, 2, ENC_BIG_ENDIAN);
1089 crc = tvb_get_ntohl(tvb, length - 4);
1090 calc_crc = update_crc(0xFFFFFFFF, tvb_get_ptr(tvb, 0, length),
1091 length);
1092 ti = proto_tree_add_uint(atm_tree, hf_atm_aal5_crc, tvb, length - 4, 4, crc);
1093 proto_item_append_text(ti, (calc_crc == 0xC704DD7B) ? " (correct)" : " (incorrect)");
1095 next_tvb = tvb_new_subset(tvb, 0, aal5_length, aal5_length);
1101 switch (pinfo->pseudo_header->atm.aal) {
1103 case AAL_SIGNALLING:
1104 call_dissector(sscop_handle, next_tvb, pinfo, tree);
1105 break;
1107 case AAL_5:
1108 switch (pinfo->pseudo_header->atm.type) {
1110 case TRAF_SSCOP:
1111 call_dissector(sscop_handle, next_tvb, pinfo, tree);
1112 break;
1114 case TRAF_FR:
1115 call_dissector(fr_handle, next_tvb, pinfo, tree);
1116 break;
1118 case TRAF_LLCMX:
1119 call_dissector(llc_handle, next_tvb, pinfo, tree);
1120 break;
1122 case TRAF_LANE:
1123 call_dissector(lane_handle, next_tvb, pinfo, tree);
1124 break;
1126 case TRAF_ILMI:
1127 call_dissector(ilmi_handle, next_tvb, pinfo, tree);
1128 break;
1130 case TRAF_GPRS_NS:
1131 call_dissector(gprs_ns_handle, next_tvb, pinfo, tree);
1132 break;
1134 default:
1136 gboolean decoded = FALSE;
1138 if (tvb_length(next_tvb) > 7) /* sizeof(octet) */
1140 guint8 octet[8];
1141 tvb_memcpy(next_tvb, octet, 0, sizeof(octet));
1143 decoded = TRUE;
1144 if (octet[0] == 0xaa
1145 && octet[1] == 0xaa
1146 && octet[2] == 0x03) /* LLC SNAP as per RFC2684 */
1148 call_dissector(llc_handle, next_tvb, pinfo, tree);
1150 else if ((pntohs(octet) & 0xff) == PPP_IP)
1152 call_dissector(ppp_handle, next_tvb, pinfo, tree);
1154 else if (pntohs(octet) == 0x00)
1156 /* assume vc muxed bridged ethernet */
1157 proto_tree_add_text(tree, tvb, 0, 2, "Pad: 0x0000");
1158 next_tvb = tvb_new_subset_remaining(tvb, 2);
1159 call_dissector(eth_handle, next_tvb, pinfo, tree);
1161 else if (octet[2] == 0x03 && /* NLPID */
1162 ((octet[3] == 0xcc || /* IPv4 */
1163 octet[3] == 0x8e) || /* IPv6 */
1164 (octet[3] == 0x00 && /* Eth */
1165 octet[4] == 0x80))) /* Eth */
1167 /* assume network interworking with FR 2 byte header */
1168 call_dissector(fr_handle, next_tvb, pinfo, tree);
1170 else if (octet[4] == 0x03 && /* NLPID */
1171 ((octet[5] == 0xcc || /* IPv4 */
1172 octet[5] == 0x8e) || /* IPv6 */
1173 (octet[5] == 0x00 && /* Eth */
1174 octet[6] == 0x80))) /* Eth */
1176 /* assume network interworking with FR 4 byte header */
1177 call_dissector(fr_handle, next_tvb, pinfo, tree);
1179 else if (((octet[0] & 0xf0)== 0x40) ||
1180 ((octet[0] & 0xf0) == 0x60))
1182 call_dissector(ip_handle, next_tvb, pinfo, tree);
1184 else
1186 decoded = FALSE;
1190 if (tree && !decoded) {
1191 /* Dump it as raw data. */
1192 call_dissector(data_handle, next_tvb, pinfo, tree);
1195 break;
1197 break;
1199 case AAL_2:
1200 proto_tree_add_uint(atm_tree, hf_atm_cid, tvb, 0, 0,
1201 pinfo->pseudo_header->atm.aal2_cid);
1202 proto_item_append_text(atm_ti, " (vpi=%u vci=%u cid=%u)",
1203 pinfo->pseudo_header->atm.vpi,
1204 pinfo->pseudo_header->atm.vci,
1205 pinfo->pseudo_header->atm.aal2_cid);
1207 if (pinfo->pseudo_header->atm.flags & ATM_AAL2_NOPHDR) {
1208 next_tvb = tvb;
1209 } else {
1210 /* Skip first 4 bytes of message
1211 - side
1212 - length
1213 - UUI
1214 Ignoring for now... */
1215 next_tvb = tvb_new_subset_remaining(tvb, 4);
1218 type = pinfo->pseudo_header->atm.type;
1219 if (type == TRAF_UNKNOWN) {
1220 type = unknown_aal2_type;
1222 switch (type) {
1223 case TRAF_UMTS_FP:
1224 call_dissector(fp_handle, next_tvb, pinfo, tree);
1225 break;
1227 default:
1228 /* Dump it as raw data. */
1229 call_dissector(data_handle, next_tvb, pinfo, tree);
1230 break;
1232 break;
1234 default:
1235 /* Dump it as raw data. */
1236 call_dissector(data_handle, next_tvb, pinfo, tree);
1237 break;
1242 * Charles Michael Heard's HEC code, from
1244 * http://www.cell-relay.com/cell-relay/publications/software/CRC/32bitCRC.tutorial.html
1246 * with the syndrome and error position tables initialized with values
1247 * computed by his "gen_syndrome_table()" and "gen_err_posn_table()" routines,
1248 * rather than by calling those routines at run time, and with various data
1249 * type cleanups and changes not to correct the header if a correctible
1250 * error was detected.
1252 #define COSET_LEADER 0x055 /* x^6 + x^4 + x^2 + 1 */
1254 static const guint8 syndrome_table[256] = {
1255 0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15,
1256 0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d,
1257 0x70, 0x77, 0x7e, 0x79, 0x6c, 0x6b, 0x62, 0x65,
1258 0x48, 0x4f, 0x46, 0x41, 0x54, 0x53, 0x5a, 0x5d,
1259 0xe0, 0xe7, 0xee, 0xe9, 0xfc, 0xfb, 0xf2, 0xf5,
1260 0xd8, 0xdf, 0xd6, 0xd1, 0xc4, 0xc3, 0xca, 0xcd,
1261 0x90, 0x97, 0x9e, 0x99, 0x8c, 0x8b, 0x82, 0x85,
1262 0xa8, 0xaf, 0xa6, 0xa1, 0xb4, 0xb3, 0xba, 0xbd,
1263 0xc7, 0xc0, 0xc9, 0xce, 0xdb, 0xdc, 0xd5, 0xd2,
1264 0xff, 0xf8, 0xf1, 0xf6, 0xe3, 0xe4, 0xed, 0xea,
1265 0xb7, 0xb0, 0xb9, 0xbe, 0xab, 0xac, 0xa5, 0xa2,
1266 0x8f, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9d, 0x9a,
1267 0x27, 0x20, 0x29, 0x2e, 0x3b, 0x3c, 0x35, 0x32,
1268 0x1f, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0d, 0x0a,
1269 0x57, 0x50, 0x59, 0x5e, 0x4b, 0x4c, 0x45, 0x42,
1270 0x6f, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7d, 0x7a,
1271 0x89, 0x8e, 0x87, 0x80, 0x95, 0x92, 0x9b, 0x9c,
1272 0xb1, 0xb6, 0xbf, 0xb8, 0xad, 0xaa, 0xa3, 0xa4,
1273 0xf9, 0xfe, 0xf7, 0xf0, 0xe5, 0xe2, 0xeb, 0xec,
1274 0xc1, 0xc6, 0xcf, 0xc8, 0xdd, 0xda, 0xd3, 0xd4,
1275 0x69, 0x6e, 0x67, 0x60, 0x75, 0x72, 0x7b, 0x7c,
1276 0x51, 0x56, 0x5f, 0x58, 0x4d, 0x4a, 0x43, 0x44,
1277 0x19, 0x1e, 0x17, 0x10, 0x05, 0x02, 0x0b, 0x0c,
1278 0x21, 0x26, 0x2f, 0x28, 0x3d, 0x3a, 0x33, 0x34,
1279 0x4e, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5c, 0x5b,
1280 0x76, 0x71, 0x78, 0x7f, 0x6a, 0x6d, 0x64, 0x63,
1281 0x3e, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2c, 0x2b,
1282 0x06, 0x01, 0x08, 0x0f, 0x1a, 0x1d, 0x14, 0x13,
1283 0xae, 0xa9, 0xa0, 0xa7, 0xb2, 0xb5, 0xbc, 0xbb,
1284 0x96, 0x91, 0x98, 0x9f, 0x8a, 0x8d, 0x84, 0x83,
1285 0xde, 0xd9, 0xd0, 0xd7, 0xc2, 0xc5, 0xcc, 0xcb,
1286 0xe6, 0xe1, 0xe8, 0xef, 0xfa, 0xfd, 0xf4, 0xf3,
1289 #define NO_ERROR_DETECTED -128
1290 #define UNCORRECTIBLE_ERROR 128
1292 static const int err_posn_table[256] = {
1293 NO_ERROR_DETECTED, 39,
1294 38, UNCORRECTIBLE_ERROR,
1295 37, UNCORRECTIBLE_ERROR,
1296 UNCORRECTIBLE_ERROR, 31,
1297 36, UNCORRECTIBLE_ERROR,
1298 UNCORRECTIBLE_ERROR, 8,
1299 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1300 30, UNCORRECTIBLE_ERROR,
1301 35, UNCORRECTIBLE_ERROR,
1302 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1303 UNCORRECTIBLE_ERROR, 23,
1304 7, UNCORRECTIBLE_ERROR,
1305 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1306 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1307 29, UNCORRECTIBLE_ERROR,
1308 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1309 34, UNCORRECTIBLE_ERROR,
1310 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1311 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1312 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1313 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1314 22, UNCORRECTIBLE_ERROR,
1315 6, UNCORRECTIBLE_ERROR,
1316 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1317 UNCORRECTIBLE_ERROR, 0,
1318 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1319 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1320 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1321 28, UNCORRECTIBLE_ERROR,
1322 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1323 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1324 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1325 33, UNCORRECTIBLE_ERROR,
1326 UNCORRECTIBLE_ERROR, 10,
1327 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
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, 12,
1334 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1335 21, UNCORRECTIBLE_ERROR,
1336 UNCORRECTIBLE_ERROR, 19,
1337 5, UNCORRECTIBLE_ERROR,
1338 UNCORRECTIBLE_ERROR, 17,
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, 3,
1345 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1346 UNCORRECTIBLE_ERROR, 15,
1347 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1348 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1349 27, UNCORRECTIBLE_ERROR,
1350 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
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 32, UNCORRECTIBLE_ERROR,
1358 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1359 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1360 9, UNCORRECTIBLE_ERROR,
1361 UNCORRECTIBLE_ERROR, 24,
1362 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1363 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1364 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1365 UNCORRECTIBLE_ERROR, 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, 1,
1371 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1372 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1373 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1374 11, UNCORRECTIBLE_ERROR,
1375 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1376 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1377 20, UNCORRECTIBLE_ERROR,
1378 UNCORRECTIBLE_ERROR, 13,
1379 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1380 18, UNCORRECTIBLE_ERROR,
1381 4, UNCORRECTIBLE_ERROR,
1382 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1383 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1384 16, UNCORRECTIBLE_ERROR,
1385 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1386 UNCORRECTIBLE_ERROR, 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, 25,
1393 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1394 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1395 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1396 2, UNCORRECTIBLE_ERROR,
1397 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1398 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1399 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1400 14, UNCORRECTIBLE_ERROR,
1401 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1402 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1403 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1404 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1405 26, UNCORRECTIBLE_ERROR,
1406 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1407 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1408 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1409 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1410 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1411 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1412 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1413 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1414 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1415 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1416 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1417 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1418 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1419 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1420 UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
1424 * Return an indication of whether there was an error in the cell header
1425 * and, if so, where the error was, if it was correctable.
1427 static int
1428 get_header_err(const guint8 *cell_header)
1430 register guint8 syndrome;
1431 register int i, err_posn;
1433 syndrome = 0;
1434 for (i = 0; i < 4; i++)
1435 syndrome = syndrome_table[syndrome ^ cell_header[i]];
1436 syndrome ^= cell_header[4] ^ COSET_LEADER;
1438 err_posn = err_posn_table [syndrome];
1440 if (err_posn < 0)
1441 return NO_ERROR_DETECTED;
1442 else if (err_posn < 40)
1443 return err_posn;
1444 else
1445 return UNCORRECTIBLE_ERROR;
1448 const value_string atm_pt_vals[] = {
1449 { 0, "User data cell, congestion not experienced, SDU-type = 0" },
1450 { 1, "User data cell, congestion not experienced, SDU-type = 1" },
1451 { 2, "User data cell, congestion experienced, SDU-type = 0" },
1452 { 3, "User data cell, congestion experienced, SDU-type = 1" },
1453 { 4, "Segment OAM F5 flow related cell" },
1454 { 5, "End-to-end OAM F5 flow related cell" },
1455 { 6, "VC resource management cell" },
1456 { 0, NULL }
1460 * Charles Michael Heard's CRC-10 code, from
1462 * http://www.cell-relay.com/cell-relay/publications/software/CRC/crc10.html
1464 * with the CRC table initialized with values computed by
1465 * his "gen_byte_crc10_table()" routine, rather than by calling that
1466 * routine at run time, and with various data type cleanups.
1468 static const guint16 byte_crc10_table[256] = {
1469 0x0000, 0x0233, 0x0255, 0x0066, 0x0299, 0x00aa, 0x00cc, 0x02ff,
1470 0x0301, 0x0132, 0x0154, 0x0367, 0x0198, 0x03ab, 0x03cd, 0x01fe,
1471 0x0031, 0x0202, 0x0264, 0x0057, 0x02a8, 0x009b, 0x00fd, 0x02ce,
1472 0x0330, 0x0103, 0x0165, 0x0356, 0x01a9, 0x039a, 0x03fc, 0x01cf,
1473 0x0062, 0x0251, 0x0237, 0x0004, 0x02fb, 0x00c8, 0x00ae, 0x029d,
1474 0x0363, 0x0150, 0x0136, 0x0305, 0x01fa, 0x03c9, 0x03af, 0x019c,
1475 0x0053, 0x0260, 0x0206, 0x0035, 0x02ca, 0x00f9, 0x009f, 0x02ac,
1476 0x0352, 0x0161, 0x0107, 0x0334, 0x01cb, 0x03f8, 0x039e, 0x01ad,
1477 0x00c4, 0x02f7, 0x0291, 0x00a2, 0x025d, 0x006e, 0x0008, 0x023b,
1478 0x03c5, 0x01f6, 0x0190, 0x03a3, 0x015c, 0x036f, 0x0309, 0x013a,
1479 0x00f5, 0x02c6, 0x02a0, 0x0093, 0x026c, 0x005f, 0x0039, 0x020a,
1480 0x03f4, 0x01c7, 0x01a1, 0x0392, 0x016d, 0x035e, 0x0338, 0x010b,
1481 0x00a6, 0x0295, 0x02f3, 0x00c0, 0x023f, 0x000c, 0x006a, 0x0259,
1482 0x03a7, 0x0194, 0x01f2, 0x03c1, 0x013e, 0x030d, 0x036b, 0x0158,
1483 0x0097, 0x02a4, 0x02c2, 0x00f1, 0x020e, 0x003d, 0x005b, 0x0268,
1484 0x0396, 0x01a5, 0x01c3, 0x03f0, 0x010f, 0x033c, 0x035a, 0x0169,
1485 0x0188, 0x03bb, 0x03dd, 0x01ee, 0x0311, 0x0122, 0x0144, 0x0377,
1486 0x0289, 0x00ba, 0x00dc, 0x02ef, 0x0010, 0x0223, 0x0245, 0x0076,
1487 0x01b9, 0x038a, 0x03ec, 0x01df, 0x0320, 0x0113, 0x0175, 0x0346,
1488 0x02b8, 0x008b, 0x00ed, 0x02de, 0x0021, 0x0212, 0x0274, 0x0047,
1489 0x01ea, 0x03d9, 0x03bf, 0x018c, 0x0373, 0x0140, 0x0126, 0x0315,
1490 0x02eb, 0x00d8, 0x00be, 0x028d, 0x0072, 0x0241, 0x0227, 0x0014,
1491 0x01db, 0x03e8, 0x038e, 0x01bd, 0x0342, 0x0171, 0x0117, 0x0324,
1492 0x02da, 0x00e9, 0x008f, 0x02bc, 0x0043, 0x0270, 0x0216, 0x0025,
1493 0x014c, 0x037f, 0x0319, 0x012a, 0x03d5, 0x01e6, 0x0180, 0x03b3,
1494 0x024d, 0x007e, 0x0018, 0x022b, 0x00d4, 0x02e7, 0x0281, 0x00b2,
1495 0x017d, 0x034e, 0x0328, 0x011b, 0x03e4, 0x01d7, 0x01b1, 0x0382,
1496 0x027c, 0x004f, 0x0029, 0x021a, 0x00e5, 0x02d6, 0x02b0, 0x0083,
1497 0x012e, 0x031d, 0x037b, 0x0148, 0x03b7, 0x0184, 0x01e2, 0x03d1,
1498 0x022f, 0x001c, 0x007a, 0x0249, 0x00b6, 0x0285, 0x02e3, 0x00d0,
1499 0x011f, 0x032c, 0x034a, 0x0179, 0x0386, 0x01b5, 0x01d3, 0x03e0,
1500 0x021e, 0x002d, 0x004b, 0x0278, 0x0087, 0x02b4, 0x02d2, 0x00e1,
1503 /* update the data block's CRC-10 remainder one byte at a time */
1504 static guint16
1505 update_crc10_by_bytes(guint16 crc10_accum, const guint8 *data_blk_ptr,
1506 int data_blk_size)
1508 register int i;
1510 for (i = 0; i < data_blk_size; i++) {
1511 crc10_accum = ((crc10_accum << 8) & 0x3ff)
1512 ^ byte_crc10_table[( crc10_accum >> 2) & 0xff]
1513 ^ *data_blk_ptr++;
1515 return crc10_accum;
1518 static const value_string st_vals[] = {
1519 { 2, "BOM" },
1520 { 0, "COM" },
1521 { 1, "EOM" },
1522 { 3, "SSM" },
1523 { 0, NULL }
1526 #define OAM_TYPE_FM 1 /* Fault Management */
1527 #define OAM_TYPE_PM 2 /* Performance Management */
1528 #define OAM_TYPE_AD 8 /* Activation/Deactivation */
1530 static const value_string oam_type_vals[] = {
1531 { OAM_TYPE_FM, "Fault Management" },
1532 { OAM_TYPE_PM, "Performance Management" },
1533 { OAM_TYPE_AD, "Activation/Deactivation" },
1534 { 0, NULL }
1537 static const value_string ft_fm_vals[] = {
1538 { 0, "Alarm Indication Signal" },
1539 { 1, "Far End Receive Failure" },
1540 { 8, "OAM Cell Loopback" },
1541 { 4, "Continuity Check" },
1542 { 0, NULL }
1545 static const value_string ft_pm_vals[] = {
1546 { 0, "Forward Monitoring" },
1547 { 1, "Backward Reporting" },
1548 { 2, "Monitoring and Reporting" },
1549 { 0, NULL }
1552 static const value_string ft_ad_vals[] = {
1553 { 0, "Performance Monitoring" },
1554 { 1, "Continuity Check" },
1555 { 0, NULL }
1560 * Check for OAM cells.
1561 * OAM F4 is VCI 3 or 4 and PT 0X0.
1562 * OAM F5 is PT 10X.
1564 gboolean
1565 atm_is_oam_cell(const guint16 vci, const guint8 pt)
1567 return (((vci == 3 || vci == 4) && ((pt & 0x5) == 0))
1568 || ((pt & 0x6) == 0x4));
1572 static void
1573 dissect_atm_cell(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1574 proto_tree *atm_tree, guint aal, gboolean nni,
1575 gboolean crc_stripped, const pwatm_private_data_t *pwpd)
1577 int offset;
1578 proto_tree *aal_tree;
1579 proto_item *ti;
1580 guint8 octet, pt;
1581 int err;
1582 guint16 vpi, vci, aal3_4_hdr, crc10;
1583 gint length;
1584 tvbuff_t *next_tvb;
1586 if (NULL == pwpd) {
1587 if (!nni) {
1589 * FF: ITU-T I.361 (Section 2.2) defines the cell header format
1590 * and encoding at UNI reference point as:
1592 * 8 7 6 5 4 3 2 1
1593 * +-+-+-+-+-+-+-+-+
1594 * | GFC | VPI |
1595 * +-+-+-+-+-+-+-+-+
1596 * | VPI | VCI |
1597 * +-+-+-+-+-+-+-+-+
1598 * | VCI |
1599 * +-+-+-+-+-+-+-+-+
1600 * | VCI | PT |C|
1601 * +-+-+-+-+-+-+-+-+
1602 * | HEC (CRC) |
1603 * +-+-+-+-+-+-+-+-+
1605 octet = tvb_get_guint8(tvb, 0);
1606 proto_tree_add_text(atm_tree, tvb, 0, 1, "GFC: 0x%x", octet >> 4);
1607 vpi = (octet & 0xF) << 4;
1608 octet = tvb_get_guint8(tvb, 1);
1609 vpi |= octet >> 4;
1610 proto_tree_add_uint(atm_tree, hf_atm_vpi, tvb, 0, 2, vpi);
1611 } else {
1613 * FF: ITU-T I.361 (Section 2.3) defines the cell header format
1614 * and encoding at NNI reference point as:
1616 * 8 7 6 5 4 3 2 1
1617 * +-+-+-+-+-+-+-+-+
1618 * | VPI |
1619 * +-+-+-+-+-+-+-+-+
1620 * | VPI | VCI |
1621 * +-+-+-+-+-+-+-+-+
1622 * | VCI |
1623 * +-+-+-+-+-+-+-+-+
1624 * | VCI | PT |C|
1625 * +-+-+-+-+-+-+-+-+
1626 * | HEC (CRC) |
1627 * +-+-+-+-+-+-+-+-+
1629 octet = tvb_get_guint8(tvb, 0);
1630 vpi = octet << 4;
1631 octet = tvb_get_guint8(tvb, 1);
1632 vpi |= (octet & 0xF0) >> 4;
1633 proto_tree_add_uint(atm_tree, hf_atm_vpi, tvb, 0, 2, vpi);
1636 vci = (octet & 0x0F) << 12;
1637 octet = tvb_get_guint8(tvb, 2);
1638 vci |= octet << 4;
1639 octet = tvb_get_guint8(tvb, 3);
1640 vci |= octet >> 4;
1641 proto_tree_add_uint(atm_tree, hf_atm_vci, tvb, 1, 3, vci);
1642 pt = (octet >> 1) & 0x7;
1643 proto_tree_add_item(atm_tree, hf_atm_payload_type, tvb, 3, 1, ENC_BIG_ENDIAN);
1644 proto_tree_add_item(atm_tree, hf_atm_cell_loss_priority, tvb, 3, 1, ENC_BIG_ENDIAN);
1646 if (!crc_stripped) {
1648 * FF: parse the Header Error Check (HEC).
1650 ti = proto_tree_add_item(atm_tree, hf_atm_header_error_check, tvb, 4, 1, ENC_BIG_ENDIAN);
1651 err = get_header_err(tvb_get_ptr(tvb, 0, 5));
1652 if (err == NO_ERROR_DETECTED)
1653 proto_item_append_text(ti, " (correct)");
1654 else if (err == UNCORRECTIBLE_ERROR)
1655 proto_item_append_text(ti, " (uncorrectable error)");
1656 else
1657 proto_item_append_text(ti, " (error in bit %d)", err);
1658 offset = 5;
1659 } else {
1661 * FF: in some encapsulation modes (e.g. RFC 4717, ATM N-to-One
1662 * Cell Mode) the Header Error Check (HEC) field is stripped.
1663 * So we do nothing here.
1665 offset = 4;
1668 else
1670 offset = 0; /* For PWs. Header is decoded by PW dissector.*/
1671 /* Not used !
1672 vpi = pwpd->vpi;
1674 vci = pwpd->vci;
1675 pt = pwpd->pti;
1679 * Check for OAM cells.
1680 * XXX - do this for all AAL values, overriding whatever information
1681 * Wiretap got from the file?
1683 if (aal == AAL_USER || aal == AAL_UNKNOWN) {
1684 if (atm_is_oam_cell(vci,pt)) {
1685 aal = AAL_OAMCELL;
1689 switch (aal) {
1691 case AAL_1:
1692 col_set_str(pinfo->cinfo, COL_PROTOCOL, "AAL1");
1693 col_clear(pinfo->cinfo, COL_INFO);
1694 ti = proto_tree_add_item(tree, proto_aal1, tvb, offset, -1, ENC_NA);
1695 aal_tree = proto_item_add_subtree(ti, ett_aal1);
1696 octet = tvb_get_guint8(tvb, offset);
1698 proto_tree_add_item(aal_tree, hf_atm_aa1_csi, tvb, offset, 1, ENC_BIG_ENDIAN);
1699 proto_tree_add_item(aal_tree, hf_atm_aa1_seq_count, tvb, offset, 1, ENC_BIG_ENDIAN);
1700 col_add_fstr(pinfo->cinfo, COL_INFO, "Sequence count = %u",
1701 (octet >> 4) & 0x7);
1702 proto_tree_add_item(aal_tree, hf_atm_aa1_crc, tvb, offset, 1, ENC_BIG_ENDIAN);
1703 proto_tree_add_item(aal_tree, hf_atm_aa1_parity, tvb, offset, 1, ENC_BIG_ENDIAN);
1704 offset++;
1706 proto_tree_add_item(aal_tree, hf_atm_aa1_payload, tvb, offset, 47, ENC_NA);
1707 break;
1709 case AAL_3_4:
1711 * XXX - or should this be the CS PDU?
1713 col_set_str(pinfo->cinfo, COL_PROTOCOL, "AAL3/4");
1714 col_clear(pinfo->cinfo, COL_INFO);
1715 ti = proto_tree_add_item(tree, proto_aal3_4, tvb, offset, -1, ENC_NA);
1716 aal_tree = proto_item_add_subtree(ti, ett_aal3_4);
1717 aal3_4_hdr = tvb_get_ntohs(tvb, offset);
1718 col_add_fstr(pinfo->cinfo, COL_INFO, "%s, sequence number = %u",
1719 val_to_str(aal3_4_hdr >> 14, st_vals, "Unknown (%u)"),
1720 (aal3_4_hdr >> 10) & 0xF);
1721 proto_tree_add_item(aal_tree, hf_atm_aal3_4_seg_type, tvb, offset, 2, ENC_BIG_ENDIAN);
1722 proto_tree_add_item(aal_tree, hf_atm_aal3_4_seq_num, tvb, offset, 2, ENC_BIG_ENDIAN);
1723 proto_tree_add_item(aal_tree, hf_atm_aal3_4_multiplex_id, tvb, offset, 2, ENC_BIG_ENDIAN);
1725 length = tvb_length_remaining(tvb, offset);
1726 crc10 = update_crc10_by_bytes(0, tvb_get_ptr(tvb, offset, length),
1727 length);
1728 offset += 2;
1730 proto_tree_add_item(aal_tree, hf_atm_aal3_4_information, tvb, offset, 44, ENC_NA);
1731 offset += 44;
1733 proto_tree_add_item(aal_tree, hf_atm_aal3_4_length_indicator, tvb, offset, 2, ENC_BIG_ENDIAN);
1734 ti = proto_tree_add_item(aal_tree, hf_atm_aal3_4_crc, tvb, offset, 2, ENC_BIG_ENDIAN);
1735 proto_item_append_text(ti, " (%s)", (crc10 == 0) ? " (correct)" : " (incorrect)");
1736 break;
1738 case AAL_OAMCELL:
1739 if (NULL == pwpd || pwpd->enable_fill_columns_by_atm_dissector)
1741 col_set_str(pinfo->cinfo, COL_PROTOCOL, "OAM AAL");
1742 col_clear(pinfo->cinfo, COL_INFO);
1744 ti = proto_tree_add_item(tree, proto_oamaal, tvb, offset, -1, ENC_NA);
1745 aal_tree = proto_item_add_subtree(ti, ett_oamaal);
1746 octet = tvb_get_guint8(tvb, offset);
1747 if (NULL == pwpd || pwpd->enable_fill_columns_by_atm_dissector)
1749 col_add_fstr(pinfo->cinfo, COL_INFO, "%s",
1750 val_to_str(octet >> 4, oam_type_vals, "Unknown (%u)"));
1753 proto_tree_add_item(aal_tree, hf_atm_aal_oamcell_type, tvb, offset, 1, ENC_BIG_ENDIAN);
1754 switch (octet >> 4) {
1756 case OAM_TYPE_FM:
1757 proto_tree_add_item(aal_tree, hf_atm_aal_oamcell_type_fm, tvb, offset, 1, ENC_BIG_ENDIAN);
1758 break;
1760 case OAM_TYPE_PM:
1761 proto_tree_add_item(aal_tree, hf_atm_aal_oamcell_type_pm, tvb, offset, 1, ENC_BIG_ENDIAN);
1762 break;
1764 case OAM_TYPE_AD:
1765 proto_tree_add_item(aal_tree, hf_atm_aal_oamcell_type_ad, tvb, offset, 1, ENC_BIG_ENDIAN);
1766 break;
1768 default:
1769 proto_tree_add_item(aal_tree, hf_atm_aal_oamcell_type_ft, tvb, offset, 1, ENC_BIG_ENDIAN);
1770 break;
1772 length = tvb_length_remaining(tvb, offset);
1773 crc10 = update_crc10_by_bytes(0, tvb_get_ptr(tvb, offset, length),
1774 length);
1775 offset += 1;
1777 proto_tree_add_item(aal_tree, hf_atm_aal_oamcell_func_spec, tvb, offset, 45, ENC_NA);
1778 offset += 45;
1780 ti = proto_tree_add_item(aal_tree, hf_atm_aal_oamcell_crc, tvb, offset, 2, ENC_BIG_ENDIAN);
1781 proto_item_append_text(ti, " (%s)", (crc10 == 0) ? " (correct)" : " (incorrect)");
1782 break;
1784 default:
1785 next_tvb = tvb_new_subset_remaining(tvb, offset);
1786 call_dissector(data_handle, next_tvb, pinfo, tree);
1787 break;
1791 static int
1792 dissect_atm_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1793 gboolean truncated, const pwatm_private_data_t *pwpd)
1795 proto_tree *atm_tree = NULL;
1796 proto_item *atm_ti = NULL;
1797 gboolean pseudowire_mode = (NULL != pwpd);
1799 if ( pinfo->pseudo_header->atm.aal == AAL_5 &&
1800 pinfo->pseudo_header->atm.type == TRAF_LANE &&
1801 dissect_lanesscop ) {
1802 pinfo->pseudo_header->atm.aal = AAL_SIGNALLING;
1805 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATM");
1807 if (!pseudowire_mode) {
1808 switch (pinfo->pseudo_header->atm.channel) {
1810 case 0:
1811 /* Traffic from DTE to DCE. */
1812 col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DCE");
1813 col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DTE");
1814 break;
1816 case 1:
1817 /* Traffic from DCE to DTE. */
1818 col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DTE");
1819 col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DCE");
1820 break;
1824 if (pinfo->pseudo_header->atm.aal == AAL_5) {
1825 col_add_fstr(pinfo->cinfo, COL_INFO, "AAL5 %s",
1826 val_to_str(pinfo->pseudo_header->atm.type, aal5_hltype_vals,
1827 "Unknown traffic type (%u)"));
1828 } else {
1829 col_add_str(pinfo->cinfo, COL_INFO,
1830 val_to_str(pinfo->pseudo_header->atm.aal, aal_vals,
1831 "Unknown AAL (%u)"));
1834 if (tree) {
1835 atm_ti = proto_tree_add_item(tree, proto_atm, tvb, 0, -1, ENC_NA);
1836 atm_tree = proto_item_add_subtree(atm_ti, ett_atm);
1838 if (!pseudowire_mode) {
1839 proto_tree_add_uint(atm_tree, hf_atm_channel, tvb, 0, 0, pinfo->pseudo_header->atm.channel);
1842 proto_tree_add_uint_format_value(atm_tree, hf_atm_aal, tvb, 0, 0,
1843 pinfo->pseudo_header->atm.aal,
1844 "%s",
1845 val_to_str(pinfo->pseudo_header->atm.aal, aal_vals,
1846 "Unknown AAL (%u)"));
1848 if (pinfo->pseudo_header->atm.flags & ATM_RAW_CELL) {
1849 /* This is a single cell, with the cell header at the beginning. */
1850 if (pinfo->pseudo_header->atm.flags & ATM_NO_HEC) {
1851 proto_item_set_len(atm_ti, 4);
1852 } else {
1853 proto_item_set_len(atm_ti, 5);
1855 dissect_atm_cell(tvb, pinfo, tree, atm_tree,
1856 pinfo->pseudo_header->atm.aal, FALSE,
1857 pinfo->pseudo_header->atm.flags & ATM_NO_HEC, pwpd);
1858 } else {
1859 /* This is a reassembled PDU. */
1862 * ATM dissector is used as "sub-dissector" for ATM pseudowires.
1863 * In such cases, the dissector data parameter is used to pass info from/to
1864 * PW dissector to ATM dissector. For decoding normal ATM traffic
1865 * data parameter should be NULL.
1867 dissect_reassembled_pdu(tvb, pinfo, tree, atm_tree, atm_ti, truncated, pwpd != NULL);
1870 return tvb_length(tvb);
1873 static int
1874 dissect_atm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
1876 const pwatm_private_data_t *pwpd = (const pwatm_private_data_t *)data;
1878 return dissect_atm_common(tvb, pinfo, tree, TRUE, pwpd);
1881 static int
1882 dissect_atm_untruncated(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
1884 const pwatm_private_data_t *pwpd = (const pwatm_private_data_t *)data;
1886 return dissect_atm_common(tvb, pinfo, tree, FALSE, pwpd);
1889 static int
1890 dissect_atm_oam_cell(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
1892 proto_tree *atm_tree = NULL;
1893 proto_item *atm_ti = NULL;
1894 const pwatm_private_data_t *pwpd = (const pwatm_private_data_t *)data;
1895 gboolean pseudowire_mode = (NULL != pwpd);
1897 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATM");
1899 if (!pseudowire_mode) {
1900 atm_ti = proto_tree_add_item(tree, proto_atm, tvb, 0, 0, ENC_NA);
1901 atm_tree = proto_item_add_subtree(atm_ti, ett_atm);
1904 dissect_atm_cell(tvb, pinfo, tree, atm_tree, AAL_OAMCELL, FALSE, FALSE, pwpd);
1905 return tvb_length(tvb);
1909 void
1910 proto_register_atm(void)
1912 static hf_register_info hf[] = {
1913 { &hf_atm_aal,
1914 { "AAL", "atm.aal", FT_UINT8, BASE_DEC, VALS(aal_vals), 0x0,
1915 NULL, HFILL }},
1917 { &hf_atm_vpi,
1918 { "VPI", "atm.vpi", FT_UINT8, BASE_DEC, NULL, 0x0,
1919 NULL, HFILL }},
1921 { &hf_atm_vci,
1922 { "VCI", "atm.vci", FT_UINT16, BASE_DEC, NULL, 0x0,
1923 NULL, HFILL }},
1925 { &hf_atm_cid,
1926 { "CID", "atm.cid", FT_UINT8, BASE_DEC, NULL, 0x0,
1927 NULL, HFILL }},
1929 { &hf_atm_le_client_client,
1930 { "LE Client", "atm.le_client.client", FT_UINT16, BASE_HEX, NULL, 0x0,
1931 NULL, HFILL }},
1932 { &hf_atm_lan_destination_tag,
1933 { "Tag", "atm.lan_destination.tag", FT_UINT16, BASE_HEX, VALS(le_control_landest_tag_vals), 0x0,
1934 NULL, HFILL }},
1935 { &hf_atm_lan_destination_mac,
1936 { "MAC address", "atm.lan_destination.mac", FT_ETHER, BASE_NONE, NULL, 0x0,
1937 NULL, HFILL }},
1938 { &hf_atm_le_control_tlv_type,
1939 { "TLV Type", "atm.le_control.tlv_type", FT_UINT32, BASE_HEX, VALS(le_tlv_type_vals), 0x0,
1940 NULL, HFILL }},
1941 { &hf_atm_le_control_tlv_length,
1942 { "TLV Length", "atm.le_control.tlv_length", FT_UINT8, BASE_DEC, NULL, 0x0,
1943 NULL, HFILL }},
1944 { &hf_atm_lan_destination_route_desc,
1945 { "Route descriptor", "atm.lan_destination.route_desc", FT_UINT16, BASE_HEX, NULL, 0x0,
1946 NULL, HFILL }},
1947 { &hf_atm_lan_destination_lan_id,
1948 { "LAN ID", "atm.lan_destination.lan_id", FT_UINT16, BASE_DEC, NULL, 0xFFF0,
1949 NULL, HFILL }},
1950 { &hf_atm_lan_destination_bridge_num,
1951 { "Bridge number", "atm.lan_destination.bridge_num", FT_UINT16, BASE_DEC, NULL, 0x000F,
1952 NULL, HFILL }},
1953 { &hf_atm_source_atm,
1954 { "Source ATM address", "atm.source_atm", FT_BYTES, BASE_NONE, NULL, 0x0,
1955 NULL, HFILL }},
1956 { &hf_atm_target_atm,
1957 { "Target ATM address", "atm.target_atm", FT_BYTES, BASE_NONE, NULL, 0x0,
1958 NULL, HFILL }},
1959 { &hf_atm_le_configure_join_frame_lan_type,
1960 { "LAN type", "atm.le_configure_join_frame.lan_type", FT_UINT8, BASE_HEX, VALS(le_control_lan_type_vals), 0x0,
1961 NULL, HFILL }},
1962 { &hf_atm_le_configure_join_frame_max_frame_size,
1963 { "Maximum frame size", "atm.le_configure_join_frame.max_frame_size", FT_UINT8, BASE_HEX, VALS(le_control_frame_size_vals), 0x0,
1964 NULL, HFILL }},
1965 { &hf_atm_le_configure_join_frame_num_tlvs,
1966 { "Number of TLVs", "atm.le_configure_join_frame.num_tlvs", FT_UINT8, BASE_DEC, NULL, 0x0,
1967 NULL, HFILL }},
1968 { &hf_atm_le_configure_join_frame_elan_name_size,
1969 { "ELAN name size", "atm.le_configure_join_frame.elan_name_size", FT_UINT8, BASE_DEC, NULL, 0x0,
1970 NULL, HFILL }},
1971 { &hf_atm_le_registration_frame_num_tlvs,
1972 { "Number of TLVs", "atm.le_registration_frame.num_tlvs", FT_UINT8, BASE_DEC, NULL, 0x0,
1973 NULL, HFILL }},
1974 { &hf_atm_le_arp_frame_num_tlvs,
1975 { "Number of TLVs", "atm.le_arp_frame.num_tlvs", FT_UINT8, BASE_DEC, NULL, 0x0,
1976 NULL, HFILL }},
1977 { &hf_atm_le_verify_frame_num_tlvs,
1978 { "Number of TLVs", "atm.le_verify_frame.num_tlvs", FT_UINT8, BASE_DEC, NULL, 0x0,
1979 NULL, HFILL }},
1980 { &hf_atm_le_configure_join_frame_elan_name,
1981 { "ELAN name", "atm.le_configure_join_frame.elan_name", FT_BYTES, BASE_NONE, NULL, 0x0,
1982 NULL, HFILL }},
1983 { &hf_atm_le_control_marker,
1984 { "Marker", "atm.le_control.marker", FT_UINT16, BASE_HEX, NULL, 0x0,
1985 NULL, HFILL }},
1986 { &hf_atm_le_control_protocol,
1987 { "Protocol", "atm.le_control.protocol", FT_UINT8, BASE_HEX, NULL, 0x0,
1988 NULL, HFILL }},
1989 { &hf_atm_le_control_version,
1990 { "Version", "atm.le_control.version", FT_UINT8, BASE_HEX, NULL, 0x0,
1991 NULL, HFILL }},
1992 { &hf_atm_le_control_opcode,
1993 { "Opcode", "atm.le_control.opcode", FT_UINT16, BASE_HEX, VALS(le_control_opcode_vals), 0x0,
1994 NULL, HFILL }},
1995 { &hf_atm_le_control_status,
1996 { "Status", "atm.le_control.status", FT_UINT16, BASE_HEX, VALS(le_control_status_vals), 0x0,
1997 NULL, HFILL }},
1998 { &hf_atm_le_control_transaction_id,
1999 { "Transaction ID", "atm.le_control.transaction_id", FT_UINT32, BASE_HEX, NULL, 0x0,
2000 NULL, HFILL }},
2001 { &hf_atm_le_control_requester_lecid,
2002 { "Requester LECID", "atm.le_control.requester_lecid", FT_UINT16, BASE_HEX, NULL, 0x0,
2003 NULL, HFILL }},
2004 { &hf_atm_le_control_flags,
2005 { "Flags", "atm.le_control.flag", FT_UINT16, BASE_HEX, NULL, 0x0,
2006 NULL, HFILL }},
2007 { &hf_atm_le_control_flag_v2_capable,
2008 { "V2 capable", "atm.le_control.flag.v2_capable", FT_BOOLEAN, 16, TFS(&tfs_yes_no), 0x0002,
2009 NULL, HFILL }},
2010 { &hf_atm_le_control_flag_selective_multicast,
2011 { "Selective multicast", "atm.le_control.flag.selective_multicast", FT_BOOLEAN, 16, TFS(&tfs_yes_no), 0x0004,
2012 NULL, HFILL }},
2013 { &hf_atm_le_control_flag_v2_required,
2014 { "V2 required", "atm.le_control.flag.v2_required", FT_BOOLEAN, 16, TFS(&tfs_yes_no), 0x0008,
2015 NULL, HFILL }},
2016 { &hf_atm_le_control_flag_proxy,
2017 { "Proxy", "atm.le_control.flag.flag_proxy", FT_BOOLEAN, 16, TFS(&tfs_yes_no), 0x0080,
2018 NULL, HFILL }},
2019 { &hf_atm_le_control_flag_exclude_explorer_frames,
2020 { "Exclude explorer frames", "atm.le_control.flag.exclude_explorer_frames", FT_BOOLEAN, 16, TFS(&tfs_yes_no), 0x0200,
2021 NULL, HFILL }},
2022 { &hf_atm_le_control_flag_address,
2023 { "Address", "atm.le_control.flag.address", FT_BOOLEAN, 16, TFS(&tfs_yes_no), 0x0001,
2024 NULL, HFILL }},
2025 { &hf_atm_le_control_topology_change,
2026 { "Topology change", "atm.le_control.flag.topology_change", FT_BOOLEAN, 16, TFS(&tfs_remote_local), 0x0100,
2027 NULL, HFILL }},
2028 { &hf_atm_traffic_type,
2029 { "Traffic type", "atm.traffic_type", FT_UINT8, BASE_DEC, VALS(aal5_hltype_vals), 0x0,
2030 NULL, HFILL }},
2031 { &hf_atm_traffic_vcmx,
2032 { "VC multiplexed traffic type", "atm.traffic.vcmx", FT_UINT8, BASE_DEC, VALS(vcmx_type_vals), 0x0,
2033 NULL, HFILL }},
2034 { &hf_atm_traffic_lane,
2035 { "LANE traffic type", "atm.traffic.lane", FT_UINT8, BASE_DEC, VALS(lane_type_vals), 0x0,
2036 NULL, HFILL }},
2037 { &hf_atm_traffic_ipsilon,
2038 { "Ipsilon traffic type", "atm.traffic.ipsilon", FT_UINT8, BASE_DEC, VALS(ipsilon_type_vals), 0x0,
2039 NULL, HFILL }},
2040 { &hf_atm_cells,
2041 { "Cells", "atm.cells", FT_UINT16, BASE_DEC, NULL, 0x0,
2042 NULL, HFILL }},
2043 { &hf_atm_aal5_uu,
2044 { "AAL5 UU", "atm.hf_atm.aal5t_uu", FT_UINT8, BASE_HEX, NULL, 0x0,
2045 NULL, HFILL }},
2046 { &hf_atm_aal5_cpi,
2047 { "AAL5 CPI", "atm.hf_atm.aal5t_cpi", FT_UINT8, BASE_HEX, NULL, 0x0,
2048 NULL, HFILL }},
2049 { &hf_atm_aal5_len,
2050 { "AAL5 len", "atm.aal5t_len", FT_UINT16, BASE_DEC, NULL, 0x0,
2051 NULL, HFILL }},
2052 { &hf_atm_aal5_crc,
2053 { "AAL5 CRC", "atm.aal5t_crc", FT_UINT32, BASE_HEX, NULL, 0x0,
2054 NULL, HFILL }},
2055 { &hf_atm_payload_type,
2056 { "Payload Type", "atm.payload_type", FT_UINT8, BASE_DEC, NULL, 0x0E,
2057 NULL, HFILL }},
2058 { &hf_atm_cell_loss_priority,
2059 { "Cell Loss Priority", "atm.cell_loss_priority", FT_BOOLEAN, 8, TFS(&tfs_low_high_priority), 0x01,
2060 NULL, HFILL }},
2061 { &hf_atm_header_error_check,
2062 { "Header Error Check", "atm.header_error_check", FT_UINT8, BASE_HEX, NULL, 0,
2063 NULL, HFILL }},
2064 { &hf_atm_channel,
2065 { "Channel", "atm.channel", FT_UINT16, BASE_DEC, VALS(atm_channel_vals), 0,
2066 NULL, HFILL }},
2067 { &hf_atm_aa1_csi,
2068 { "CSI", "atm.aa1.csi", FT_UINT8, BASE_DEC, NULL, 0x80,
2069 NULL, HFILL }},
2070 { &hf_atm_aa1_seq_count,
2071 { "Sequence Count", "atm.aa1.seq_count", FT_UINT8, BASE_DEC, NULL, 0x70,
2072 NULL, HFILL }},
2073 { &hf_atm_aa1_crc,
2074 { "CRC", "atm.aa1.crc", FT_UINT8, BASE_DEC, NULL, 0x08,
2075 NULL, HFILL }},
2076 { &hf_atm_aa1_parity,
2077 { "Parity", "atm.aa1.parity", FT_UINT8, BASE_DEC, NULL, 0x07,
2078 NULL, HFILL }},
2079 { &hf_atm_aa1_payload,
2080 { "Payload", "atm.aa1.payload", FT_BYTES, BASE_NONE, NULL, 0x0,
2081 NULL, HFILL }},
2082 { &hf_atm_aal3_4_seg_type,
2083 { "Segment Type", "atm.aal3_4.seg_type", FT_UINT16, BASE_DEC, VALS(st_vals), 0xC000,
2084 NULL, HFILL }},
2085 { &hf_atm_aal3_4_seq_num,
2086 { "Sequence Number", "atm.aal3_4.seq_num", FT_UINT16, BASE_DEC, NULL, 0x3C00,
2087 NULL, HFILL }},
2088 { &hf_atm_aal3_4_multiplex_id,
2089 { "Multiplex ID", "atm.aal3_4.multiplex_id", FT_UINT16, BASE_DEC, NULL, 0x03FF,
2090 NULL, HFILL }},
2091 { &hf_atm_aal3_4_information,
2092 { "Information", "atm.aal3_4.information", FT_BYTES, BASE_NONE, NULL, 0x0,
2093 NULL, HFILL }},
2094 { &hf_atm_aal3_4_length_indicator,
2095 { "Length Indicator", "atm.aal3_4.length_indicator", FT_UINT16, BASE_DEC, VALS(st_vals), 0xFC00,
2096 NULL, HFILL }},
2097 { &hf_atm_aal3_4_crc,
2098 { "CRC", "atm.aal3_4.crc", FT_UINT16, BASE_DEC, NULL, 0x03FF,
2099 NULL, HFILL }},
2100 { &hf_atm_aal_oamcell_type,
2101 { "OAM Type", "atm.aal_oamcell.type", FT_UINT8, BASE_DEC, VALS(oam_type_vals), 0xF0,
2102 NULL, HFILL }},
2103 { &hf_atm_aal_oamcell_type_fm,
2104 { "Function Type", "atm.aal_oamcell.type.fm", FT_UINT8, BASE_DEC, VALS(ft_fm_vals), 0x0F,
2105 NULL, HFILL }},
2106 { &hf_atm_aal_oamcell_type_pm,
2107 { "Function Type", "atm.aal_oamcell.type.pm", FT_UINT8, BASE_DEC, VALS(ft_pm_vals), 0x0F,
2108 NULL, HFILL }},
2109 { &hf_atm_aal_oamcell_type_ad,
2110 { "Function Type", "atm.aal_oamcell.type.ad", FT_UINT8, BASE_DEC, VALS(ft_ad_vals), 0x0F,
2111 NULL, HFILL }},
2112 { &hf_atm_aal_oamcell_type_ft,
2113 { "Function Type", "atm.aal_oamcell.type.ft", FT_UINT8, BASE_DEC, NULL, 0x0F,
2114 NULL, HFILL }},
2115 { &hf_atm_aal_oamcell_func_spec,
2116 { "Function-specific information", "atm.aal_oamcell.func_spec", FT_BYTES, BASE_NONE, NULL, 0x0,
2117 NULL, HFILL }},
2118 { &hf_atm_aal_oamcell_crc,
2119 { "CRC-10", "atm.aal_oamcell.crc", FT_UINT16, BASE_HEX, NULL, 0x3FF,
2120 NULL, HFILL }},
2123 static gint *ett[] = {
2124 &ett_atm,
2125 &ett_ilmi,
2126 &ett_aal1,
2127 &ett_aal3_4,
2128 &ett_oamaal,
2129 &ett_atm_lane,
2130 &ett_atm_lane_lc_lan_dest,
2131 &ett_atm_lane_lc_lan_dest_rd,
2132 &ett_atm_lane_lc_flags,
2133 &ett_atm_lane_lc_tlv,
2136 static const enum_val_t unknown_aal2_options[] = {
2137 { "raw", "Raw data", TRAF_UNKNOWN },
2138 { "umts_fp", "UMTS FP", TRAF_UMTS_FP },
2139 { NULL, NULL, 0 }
2142 module_t *atm_module;
2144 proto_atm = proto_register_protocol("Asynchronous Transfer Mode", "ATM", "atm");
2145 proto_aal1 = proto_register_protocol("ATM AAL1", "AAL1", "aal1");
2146 proto_aal3_4 = proto_register_protocol("ATM AAL3/4", "AAL3/4", "aal3_4");
2147 proto_oamaal = proto_register_protocol("ATM OAM AAL", "OAM AAL", "oamaal");
2148 proto_register_field_array(proto_atm, hf, array_length(hf));
2149 proto_register_subtree_array(ett, array_length(ett));
2151 proto_ilmi = proto_register_protocol("ILMI", "ILMI", "ilmi");
2153 register_dissector("ilmi", dissect_ilmi, proto_ilmi);
2155 proto_atm_lane = proto_register_protocol("ATM LAN Emulation",
2156 "ATM LANE", "lane");
2158 register_dissector("lane", dissect_lane, proto_atm_lane);
2159 atm_handle = new_register_dissector("atm_truncated", dissect_atm, proto_atm);
2160 atm_untruncated_handle = new_register_dissector("atm_untruncated", dissect_atm_untruncated, proto_atm);
2161 new_register_dissector("atm_oam_cell", dissect_atm_oam_cell, proto_oamaal);
2163 atm_module = prefs_register_protocol ( proto_atm, NULL );
2164 prefs_register_bool_preference(atm_module, "dissect_lane_as_sscop", "Dissect LANE as SSCOP",
2165 "Autodection between LANE and SSCOP is hard. As default LANE is preferred",
2166 &dissect_lanesscop);
2167 prefs_register_enum_preference(atm_module, "unknown_aal2_type",
2168 "Decode unknown AAL2 traffic as",
2169 "Type used to dissect unknown AAL2 traffic",
2170 &unknown_aal2_type, unknown_aal2_options, FALSE);
2174 void
2175 proto_reg_handoff_atm(void)
2178 * Get handles for the Ethernet, Token Ring, Frame Relay, LLC,
2179 * SSCOP, LANE, and ILMI dissectors.
2181 eth_withoutfcs_handle = find_dissector("eth_withoutfcs");
2182 tr_handle = find_dissector("tr");
2183 fr_handle = find_dissector("fr");
2184 llc_handle = find_dissector("llc");
2185 sscop_handle = find_dissector("sscop");
2186 lane_handle = find_dissector("lane");
2187 ilmi_handle = find_dissector("ilmi");
2188 ppp_handle = find_dissector("ppp");
2189 eth_handle = find_dissector("eth");
2190 ip_handle = find_dissector("ip");
2191 data_handle = find_dissector("data");
2192 fp_handle = find_dissector("fp");
2193 gprs_ns_handle = find_dissector("gprs_ns");
2195 dissector_add_uint("wtap_encap", WTAP_ENCAP_ATM_PDUS, atm_handle);
2197 dissector_add_uint("wtap_encap", WTAP_ENCAP_ATM_PDUS_UNTRUNCATED,
2198 atm_untruncated_handle);