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.3 2003/10/28 18:08:52 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;
145 /* FORWARD DECLARATIONS */
147 void proto_reg_handoff_bssap(void);
150 dissect_bssap_unknown_message(tvbuff_t *message_tvb, proto_tree *bssap_tree)
152 guint32 message_length;
154 message_length = tvb_length(message_tvb);
156 proto_tree_add_text(bssap_tree, message_tvb, 0, message_length,
157 "Unknown message (%u byte%s)",
158 message_length, plurality(message_length, "", "s"));
162 dissect_bssap_unknown_param(tvbuff_t *tvb, proto_tree *tree, guint8 type, guint16 length)
164 proto_tree_add_text(tree, tvb, 0, length,
165 "Unknown parameter 0x%x (%u byte%s)",
166 type, length, plurality(length, "", "s"));
170 dissect_bssap_data_param(tvbuff_t *tvb, packet_info *pinfo,
171 proto_tree *bssap_tree, proto_tree *tree)
173 if ((pdu_type <= 0x01))
175 if (bssap_or_bsap_global == BSSAP)
178 if (dissector_try_port(bssap_dissector_table, pdu_type, tvb, pinfo, tree)) return;
183 if (dissector_try_port(bsap_dissector_table, pdu_type, tvb, pinfo, tree)) return;
187 /* No sub-dissection occured, treat it as raw data */
188 call_dissector(data_handle, tvb, pinfo, bssap_tree);
192 dissect_bssap_dlci_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
194 proto_item *dlci_item = 0;
195 proto_tree *dlci_tree = 0;
199 proto_tree_add_text(tree, tvb, 0, length,
200 "Data Link Connection Identifier");
202 dlci_tree = proto_item_add_subtree(dlci_item, ett_bssap_dlci);
204 oct = tvb_get_guint8(tvb, 0);
206 if (bssap_or_bsap_global == BSSAP)
208 proto_tree_add_uint(dlci_tree, hf_bssap_dlci_cc, tvb, 0, length, oct);
209 proto_tree_add_uint(dlci_tree, hf_bssap_dlci_spare, tvb, 0, length, oct);
210 proto_tree_add_uint(dlci_tree, hf_bssap_dlci_sapi, tvb, 0, length, oct);
214 proto_tree_add_uint(dlci_tree, hf_bsap_dlci_cc, tvb, 0, length, oct);
215 proto_tree_add_uint(dlci_tree, hf_bsap_dlci_rsvd, tvb, 0, length, oct);
216 proto_tree_add_uint(dlci_tree, hf_bsap_dlci_sapi, tvb, 0, length, oct);
221 dissect_bssap_length_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
225 data_length = tvb_get_guint8(tvb, 0);
226 proto_tree_add_uint(tree, hf_bssap_length, tvb, 0, length, data_length);
230 * Dissect a parameter given its type, offset into tvb, and length.
233 dissect_bssap_parameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bssap_tree,
234 proto_tree *tree, guint8 parameter_type, guint8 offset,
235 guint16 parameter_length)
237 tvbuff_t *parameter_tvb;
239 parameter_tvb = tvb_new_subset(tvb, offset, parameter_length, parameter_length);
241 switch (parameter_type)
244 dissect_bssap_dlci_param(parameter_tvb, bssap_tree, parameter_length);
247 case PARAMETER_LENGTH:
248 dissect_bssap_length_param(parameter_tvb, bssap_tree, parameter_length);
252 dissect_bssap_data_param(parameter_tvb, pinfo, bssap_tree, tree);
256 dissect_bssap_unknown_param(parameter_tvb, bssap_tree, parameter_type,
261 return(parameter_length);
265 dissect_bssap_var_parameter(tvbuff_t *tvb, packet_info *pinfo,
266 proto_tree *bssap_tree, proto_tree *tree,
267 guint8 parameter_type, guint8 offset)
269 guint16 parameter_length;
270 guint8 length_length;
272 parameter_length = tvb_get_guint8(tvb, offset);
273 length_length = LENGTH_LENGTH;
275 offset += length_length;
277 dissect_bssap_parameter(tvb, pinfo, bssap_tree, tree, parameter_type,
278 offset, parameter_length);
280 return(parameter_length + length_length);
284 dissect_bssap_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bssap_tree,
290 * Extract the PDU type
292 pdu_type = tvb_get_guint8(tvb, PDU_TYPE_OFFSET);
293 offset = PDU_TYPE_LENGTH;
298 * add the message type to the protocol tree
300 proto_tree_add_uint(bssap_tree,
301 (bssap_or_bsap_global == BSSAP) ? hf_bssap_pdu_type : hf_bsap_pdu_type,
302 tvb, PDU_TYPE_OFFSET, PDU_TYPE_LENGTH, pdu_type);
305 /* Starting a new message dissection */
309 case BSSAP_PDU_TYPE_BSSMAP:
310 offset += dissect_bssap_parameter(tvb, pinfo, bssap_tree, tree,
311 PARAMETER_LENGTH, offset,
313 offset += dissect_bssap_var_parameter(tvb, pinfo, bssap_tree, tree,
315 (offset - LENGTH_LENGTH));
318 case BSSAP_PDU_TYPE_DTAP:
319 offset += dissect_bssap_parameter(tvb, pinfo, bssap_tree, tree,
321 offset, DLCI_LENGTH);
322 offset += dissect_bssap_parameter(tvb, pinfo, bssap_tree, tree,
323 PARAMETER_LENGTH, offset,
325 offset += dissect_bssap_var_parameter(tvb, pinfo, bssap_tree, tree,
327 (offset - LENGTH_LENGTH));
331 if (check_col(pinfo->cinfo, COL_INFO))
333 col_append_fstr(pinfo->cinfo, COL_INFO, "%s ",
334 val_to_str(pdu_type, ((bssap_or_bsap_global == BSSAP) ?
335 bssap_pdu_type_acro_values : bsap_pdu_type_acro_values),
340 dissect_bssap_unknown_message(tvb, bssap_tree);
346 dissect_bssap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
348 proto_item *bssap_item;
349 proto_tree *bssap_tree = NULL;
352 * Make entry in the Protocol column on summary display
354 if (check_col(pinfo->cinfo, COL_PROTOCOL))
356 col_set_str(pinfo->cinfo, COL_PROTOCOL, ((bssap_or_bsap_global == BSSAP) ? "BSSAP" : "BSAP"));
362 * create the bssap protocol tree
364 proto_tree_add_item_hidden(tree, proto_bssap, tvb, 0, -1, FALSE);
365 bssap_item = proto_tree_add_text(tree, tvb, 0, -1, (bssap_or_bsap_global == BSSAP) ? "BSSAP" : "BSAP");
366 bssap_tree = proto_item_add_subtree(bssap_item, ett_bssap);
369 /* dissect the message */
371 dissect_bssap_message(tvb, pinfo, bssap_tree, tree);
375 dissect_bssap_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
377 /* Is it a BSSAP/BSAP packet?
378 * If octet_1 == 0x00 and octet_2 == length(tvb) - 2
379 * or if octet_1 == 0x01 and octet_3 == length(tvb) - 3
380 * then we'll assume it is a bssap packet
382 switch (tvb_get_guint8(tvb, 0))
385 if (tvb_get_guint8(tvb, 1) != (tvb_length(tvb) - 2)) { return(FALSE); }
389 if (tvb_get_guint8(tvb, 2) != (tvb_length(tvb) - 3)) { return(FALSE); }
396 dissect_bssap(tvb, pinfo, tree);
401 /* Register the protocol with Ethereal */
403 proto_register_bssap(void)
405 module_t *bssap_module;
407 /* Setup list of header fields */
408 static hf_register_info hf[] = {
409 { &hf_bssap_pdu_type,
410 { "Message Type", "bssap.pdu_type",
411 FT_UINT8, BASE_HEX, VALS(bssap_pdu_type_values), 0x0,
414 { "Message Type", "bsap.pdu_type",
415 FT_UINT8, BASE_HEX, VALS(bsap_pdu_type_values), 0x0,
418 { "Control Channel", "bssap.dlci.cc",
419 FT_UINT8, BASE_HEX, VALS(bssap_cc_values), CC_MASK,
422 { "Control Channel", "bsap.dlci.cc",
423 FT_UINT8, BASE_HEX, VALS(bsap_cc_values), CC_MASK,
425 { &hf_bssap_dlci_spare,
426 { "Spare", "bssap.dlci.spare",
427 FT_UINT8, BASE_HEX, NULL, SPARE_MASK,
429 { &hf_bsap_dlci_rsvd,
430 { "Reserved", "bsap.dlci.rsvd",
431 FT_UINT8, BASE_HEX, NULL, SPARE_MASK,
433 { &hf_bssap_dlci_sapi,
434 { "SAPI", "bssap.dlci.sapi",
435 FT_UINT8, BASE_HEX, VALS(bssap_sapi_values), SAPI_MASK,
437 { &hf_bsap_dlci_sapi,
438 { "SAPI", "bsap.dlci.sapi",
439 FT_UINT8, BASE_HEX, VALS(bsap_sapi_values), SAPI_MASK,
442 { "Length", "bssap.length",
443 FT_UINT8, BASE_DEC, NULL, 0x0,
447 /* Setup protocol subtree array */
448 static gint *ett[] = {
453 static enum_val_t bssap_or_bsap_options[] = {
460 /* Register the protocol name and description */
461 proto_bssap = proto_register_protocol("BSSAP/BSAP", "BSSAP", "bssap");
463 /* Required function calls to register the header fields and subtrees used */
464 proto_register_field_array(proto_bssap, hf, array_length(hf));
465 proto_register_subtree_array(ett, array_length(ett));
467 bssap_module = prefs_register_protocol(proto_bssap, proto_reg_handoff_bssap);
469 prefs_register_enum_preference(bssap_module,
471 "Identify to sub-dissector as",
472 "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.",
473 &bssap_or_bsap_global,
474 bssap_or_bsap_options,
477 bssap_dissector_table = register_dissector_table("bssap.pdu_type", "BSSAP Message Type", FT_UINT8, BASE_DEC);
478 bsap_dissector_table = register_dissector_table("bsap.pdu_type", "BSAP Message Type", FT_UINT8, BASE_DEC);
482 proto_reg_handoff_bssap(void)
484 static gboolean bssap_prefs_initialized = FALSE;
487 if (!bssap_prefs_initialized)
489 heur_dissector_add("sccp", dissect_bssap_heur, proto_bssap);
491 bssap_prefs_initialized = TRUE;
494 data_handle = find_dissector("data");