2 * Routines for Base Station Subsystem Application Part (BSSAP/BSAP) dissection
3 * Specifications from 3GPP2 (www.3gpp2.org) and 3GPP (www.3gpp.org)
7 * Copyright 2003, Michael Lum <mlum [AT] telostech.com>
8 * In association with Telos Technology Inc.
10 * $Id: packet-bssap.c,v 1.9 2003/12/17 23:54:44 guy Exp $
12 * Ethereal - Network traffic analyzer
13 * By Gerald Combs <gerald@ethereal.com>
14 * Copyright 1998 Gerald Combs
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
39 #ifdef HAVE_SYS_TYPES_H
40 # include <sys/types.h>
43 #ifdef HAVE_NETINET_IN_H
44 # include <netinet/in.h>
49 #include "epan/packet.h"
51 #include "packet-bssap.h"
56 #define BSSAP_OR_BSAP_DEFAULT BSSAP
58 #define PDU_TYPE_OFFSET 0
59 #define PDU_TYPE_LENGTH 1
61 /* Same as below but with names typed out */
62 static const value_string bssap_pdu_type_values[] = {
63 { BSSAP_PDU_TYPE_BSSMAP, "BSS Management" },
64 { BSSAP_PDU_TYPE_DTAP, "Direct Transfer" },
67 static const value_string bsap_pdu_type_values[] = {
68 { BSSAP_PDU_TYPE_BSSMAP, "BS Management" },
69 { BSSAP_PDU_TYPE_DTAP, "Direct Transfer" },
72 /* Same as above but in acronym for (for the Info column) */
73 static const value_string bssap_pdu_type_acro_values[] = {
74 { BSSAP_PDU_TYPE_BSSMAP, "BSSMAP" },
75 { BSSAP_PDU_TYPE_DTAP, "DTAP" },
78 /* Same as above but in acronym for (for the Info column) */
79 static const value_string bsap_pdu_type_acro_values[] = {
80 { BSSAP_PDU_TYPE_BSSMAP, "BSMAP" },
81 { BSSAP_PDU_TYPE_DTAP, "DTAP" },
84 #define PARAMETER_DLCI 0x00
85 #define PARAMETER_LENGTH 0x01
86 #define PARAMETER_DATA 0x02
89 #define LENGTH_LENGTH 1
93 #define SPARE_MASK 0x38
94 #define SAPI_MASK 0x07
96 static const value_string bssap_cc_values[] = {
97 { 0x00, "not further specified" },
98 { 0x80, "FACCH or SDCCH" },
102 static const value_string bsap_cc_values[] = {
103 { 0x00, "default for TIA/EIA/IS-2000" },
106 static const value_string bssap_sapi_values[] = {
107 { 0x00, "RR/MM/CC" },
111 static const value_string bsap_sapi_values[] = {
112 { 0x00, "Not used" },
116 /* Initialize the protocol and registered fields */
117 static int proto_bssap = -1;
118 static int hf_bssap_pdu_type = -1;
119 static int hf_bsap_pdu_type = -1;
120 static int hf_bssap_dlci_cc = -1;
121 static int hf_bsap_dlci_cc = -1;
122 static int hf_bssap_dlci_spare = -1;
123 static int hf_bsap_dlci_rsvd = -1;
124 static int hf_bssap_dlci_sapi = -1;
125 static int hf_bsap_dlci_sapi = -1;
126 static int hf_bssap_length = -1;
128 /* Initialize the subtree pointers */
129 static gint ett_bssap = -1;
130 static gint ett_bssap_dlci = -1;
132 static dissector_handle_t data_handle;
134 static dissector_table_t bssap_dissector_table;
135 static dissector_table_t bsap_dissector_table;
138 * Keep track of pdu_type so we can call appropriate sub-dissector
140 static guint8 pdu_type = 0xFF;
142 static guint bssap_or_bsap_global = BSSAP_OR_BSAP_DEFAULT;
146 dissect_bssap_unknown_message(tvbuff_t *message_tvb, proto_tree *bssap_tree)
148 guint32 message_length;
150 message_length = tvb_length(message_tvb);
152 proto_tree_add_text(bssap_tree, message_tvb, 0, message_length,
153 "Unknown message (%u byte%s)",
154 message_length, plurality(message_length, "", "s"));
158 dissect_bssap_unknown_param(tvbuff_t *tvb, proto_tree *tree, guint8 type, guint16 length)
160 proto_tree_add_text(tree, tvb, 0, length,
161 "Unknown parameter 0x%x (%u byte%s)",
162 type, length, plurality(length, "", "s"));
166 dissect_bssap_data_param(tvbuff_t *tvb, packet_info *pinfo,
167 proto_tree *bssap_tree, proto_tree *tree)
169 if ((pdu_type <= 0x01))
171 if (bssap_or_bsap_global == BSSAP)
174 if (dissector_try_port(bssap_dissector_table, pdu_type, tvb, pinfo, tree)) return;
179 if (dissector_try_port(bsap_dissector_table, pdu_type, tvb, pinfo, tree)) return;
183 /* No sub-dissection occured, treat it as raw data */
184 call_dissector(data_handle, tvb, pinfo, bssap_tree);
188 dissect_bssap_dlci_param(tvbuff_t *tvb, proto_tree *tree, guint16 length)
190 proto_item *dlci_item = 0;
191 proto_tree *dlci_tree = 0;
195 proto_tree_add_text(tree, tvb, 0, length,
196 "Data Link Connection Identifier");
198 dlci_tree = proto_item_add_subtree(dlci_item, ett_bssap_dlci);
200 oct = tvb_get_guint8(tvb, 0);
202 if (bssap_or_bsap_global == BSSAP)
204 proto_tree_add_uint(dlci_tree, hf_bssap_dlci_cc, tvb, 0, length, oct);
205 proto_tree_add_uint(dlci_tree, hf_bssap_dlci_spare, tvb, 0, length, oct);
206 proto_tree_add_uint(dlci_tree, hf_bssap_dlci_sapi, tvb, 0, length, oct);
210 proto_tree_add_uint(dlci_tree, hf_bsap_dlci_cc, tvb, 0, length, oct);
211 proto_tree_add_uint(dlci_tree, hf_bsap_dlci_rsvd, tvb, 0, length, oct);
212 proto_tree_add_uint(dlci_tree, hf_bsap_dlci_sapi, tvb, 0, length, oct);
217 dissect_bssap_length_param(tvbuff_t *tvb, proto_tree *tree, guint16 length)
221 data_length = tvb_get_guint8(tvb, 0);
222 proto_tree_add_uint(tree, hf_bssap_length, tvb, 0, length, data_length);
226 * Dissect a parameter given its type, offset into tvb, and length.
229 dissect_bssap_parameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bssap_tree,
230 proto_tree *tree, guint8 parameter_type, gint offset,
231 guint16 parameter_length)
233 tvbuff_t *parameter_tvb;
235 parameter_tvb = tvb_new_subset(tvb, offset, parameter_length, parameter_length);
237 switch (parameter_type)
240 dissect_bssap_dlci_param(parameter_tvb, bssap_tree, parameter_length);
243 case PARAMETER_LENGTH:
244 dissect_bssap_length_param(parameter_tvb, bssap_tree, parameter_length);
248 dissect_bssap_data_param(parameter_tvb, pinfo, bssap_tree, tree);
252 dissect_bssap_unknown_param(parameter_tvb, bssap_tree, parameter_type,
257 return(parameter_length);
261 dissect_bssap_var_parameter(tvbuff_t *tvb, packet_info *pinfo,
262 proto_tree *bssap_tree, proto_tree *tree,
263 guint8 parameter_type, gint offset)
265 guint16 parameter_length;
266 guint8 length_length;
268 parameter_length = tvb_get_guint8(tvb, offset);
269 length_length = LENGTH_LENGTH;
271 offset += length_length;
273 dissect_bssap_parameter(tvb, pinfo, bssap_tree, tree, parameter_type,
274 offset, parameter_length);
276 return(parameter_length + length_length);
280 dissect_bssap_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bssap_tree,
286 * Extract the PDU type
288 pdu_type = tvb_get_guint8(tvb, PDU_TYPE_OFFSET);
289 offset = PDU_TYPE_LENGTH;
294 * add the message type to the protocol tree
296 proto_tree_add_uint(bssap_tree,
297 (bssap_or_bsap_global == BSSAP) ? hf_bssap_pdu_type : hf_bsap_pdu_type,
298 tvb, PDU_TYPE_OFFSET, PDU_TYPE_LENGTH, pdu_type);
301 /* Starting a new message dissection */
305 case BSSAP_PDU_TYPE_BSSMAP:
306 offset += dissect_bssap_parameter(tvb, pinfo, bssap_tree, tree,
307 PARAMETER_LENGTH, offset,
309 offset += dissect_bssap_var_parameter(tvb, pinfo, bssap_tree, tree,
311 (offset - LENGTH_LENGTH));
314 case BSSAP_PDU_TYPE_DTAP:
315 offset += dissect_bssap_parameter(tvb, pinfo, bssap_tree, tree,
317 offset, DLCI_LENGTH);
318 offset += dissect_bssap_parameter(tvb, pinfo, bssap_tree, tree,
319 PARAMETER_LENGTH, offset,
321 offset += dissect_bssap_var_parameter(tvb, pinfo, bssap_tree, tree,
323 (offset - LENGTH_LENGTH));
327 if (check_col(pinfo->cinfo, COL_INFO))
329 col_append_fstr(pinfo->cinfo, COL_INFO, "%s ",
330 val_to_str(pdu_type, ((bssap_or_bsap_global == BSSAP) ?
331 bssap_pdu_type_acro_values : bsap_pdu_type_acro_values),
336 dissect_bssap_unknown_message(tvb, bssap_tree);
342 dissect_bssap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
344 proto_item *bssap_item;
345 proto_tree *bssap_tree = NULL;
348 * Make entry in the Protocol column on summary display
350 if (check_col(pinfo->cinfo, COL_PROTOCOL))
352 col_set_str(pinfo->cinfo, COL_PROTOCOL, ((bssap_or_bsap_global == BSSAP) ? "BSSAP" : "BSAP"));
356 * create the bssap protocol tree
358 proto_tree_add_item_hidden(tree, proto_bssap, tvb, 0, -1, FALSE);
359 bssap_item = proto_tree_add_text(tree, tvb, 0, -1, (bssap_or_bsap_global == BSSAP) ? "BSSAP" : "BSAP");
360 bssap_tree = proto_item_add_subtree(bssap_item, ett_bssap);
362 /* dissect the message */
364 dissect_bssap_message(tvb, pinfo, bssap_tree, tree);
368 dissect_bssap_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
370 /* Is it a BSSAP/BSAP packet?
371 * If octet_1 == 0x00 and octet_2 == length(tvb) - 2
372 * or if octet_1 == 0x01 and octet_3 == length(tvb) - 3
373 * then we'll assume it is a bssap packet
375 switch (tvb_get_guint8(tvb, 0))
378 if (tvb_get_guint8(tvb, 1) != (tvb_length(tvb) - 2)) { return(FALSE); }
382 if (tvb_get_guint8(tvb, 2) != (tvb_length(tvb) - 3)) { return(FALSE); }
389 dissect_bssap(tvb, pinfo, tree);
394 /* Register the protocol with Ethereal */
396 proto_register_bssap(void)
398 module_t *bssap_module;
400 /* Setup list of header fields */
401 static hf_register_info hf[] = {
402 { &hf_bssap_pdu_type,
403 { "Message Type", "bssap.pdu_type",
404 FT_UINT8, BASE_HEX, VALS(bssap_pdu_type_values), 0x0,
407 { "Message Type", "bsap.pdu_type",
408 FT_UINT8, BASE_HEX, VALS(bsap_pdu_type_values), 0x0,
411 { "Control Channel", "bssap.dlci.cc",
412 FT_UINT8, BASE_HEX, VALS(bssap_cc_values), CC_MASK,
415 { "Control Channel", "bsap.dlci.cc",
416 FT_UINT8, BASE_HEX, VALS(bsap_cc_values), CC_MASK,
418 { &hf_bssap_dlci_spare,
419 { "Spare", "bssap.dlci.spare",
420 FT_UINT8, BASE_HEX, NULL, SPARE_MASK,
422 { &hf_bsap_dlci_rsvd,
423 { "Reserved", "bsap.dlci.rsvd",
424 FT_UINT8, BASE_HEX, NULL, SPARE_MASK,
426 { &hf_bssap_dlci_sapi,
427 { "SAPI", "bssap.dlci.sapi",
428 FT_UINT8, BASE_HEX, VALS(bssap_sapi_values), SAPI_MASK,
430 { &hf_bsap_dlci_sapi,
431 { "SAPI", "bsap.dlci.sapi",
432 FT_UINT8, BASE_HEX, VALS(bsap_sapi_values), SAPI_MASK,
435 { "Length", "bssap.length",
436 FT_UINT8, BASE_DEC, NULL, 0x0,
440 /* Setup protocol subtree array */
441 static gint *ett[] = {
446 static enum_val_t bssap_or_bsap_options[] = {
453 /* Register the protocol name and description */
454 proto_bssap = proto_register_protocol("BSSAP/BSAP", "BSSAP", "bssap");
456 /* Required function calls to register the header fields and subtrees used */
457 proto_register_field_array(proto_bssap, hf, array_length(hf));
458 proto_register_subtree_array(ett, array_length(ett));
460 bssap_module = prefs_register_protocol(proto_bssap, NULL);
462 prefs_register_enum_preference(bssap_module,
464 "Identify to sub-dissector as",
465 "For the sake of sub-dissectors registering to accept data from the BSSAP/BSAP dissector, this defines whether it is identified as BSSAP or BSAP.",
466 &bssap_or_bsap_global,
467 bssap_or_bsap_options,
470 bssap_dissector_table = register_dissector_table("bssap.pdu_type", "BSSAP Message Type", FT_UINT8, BASE_DEC);
471 bsap_dissector_table = register_dissector_table("bsap.pdu_type", "BSAP Message Type", FT_UINT8, BASE_DEC);
475 proto_reg_handoff_bssap(void)
477 heur_dissector_add("sccp", dissect_bssap_heur, proto_bssap);
479 data_handle = find_dissector("data");