2 * Helper-dissector for Tektronix k12xx-k15xx .rf5 file type
4 * Luis E. Garcia Ontanon <luis@ontanon.org>
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
31 #include <wsutil/str_util.h>
32 #include <epan/packet.h>
33 #include <wsutil/pint.h>
34 #include <epan/conversation.h>
36 #include <epan/emem.h>
37 #include <epan/wmem/wmem.h>
39 #include <epan/expert.h>
40 #include <epan/strutil.h>
41 #include "packet-sscop.h"
42 #include "packet-umts_fp.h"
44 typedef struct _k12_hdls_t
{
47 dissector_handle_t
* handles
;
50 static int proto_k12
= -1;
52 static int hf_k12_port_id
= -1;
53 static int hf_k12_port_name
= -1;
54 static int hf_k12_stack_file
= -1;
55 static int hf_k12_port_type
= -1;
56 static int hf_k12_atm_vp
= -1;
57 static int hf_k12_atm_vc
= -1;
58 static int hf_k12_atm_cid
= -1;
60 static int hf_k12_ts
= -1;
62 static gint ett_k12
= -1;
63 static gint ett_port
= -1;
64 static gint ett_stack_item
= -1;
66 static expert_field ei_k12_unmatched_stk_file
= EI_INIT
;
68 static dissector_handle_t k12_handle
;
69 static dissector_handle_t data_handle
;
70 static dissector_handle_t sscop_handle
;
71 static dissector_handle_t fp_handle
;
73 extern int proto_sscop
;
76 static wmem_tree_t
* port_handles
= NULL
;
77 static uat_t
* k12_uat
= NULL
;
78 static k12_handles_t
* k12_handles
= NULL
;
79 static guint nk12_handles
= 0;
81 static const value_string k12_port_types
[] = {
82 { K12_PORT_DS1
, "Ds1" },
83 { K12_PORT_DS0S
, "Ds0 Range" },
84 { K12_PORT_ATMPVC
, "ATM PVC" },
89 fill_fp_info(fp_info
*p_fp_info
, guchar
*extra_info
, guint32 length
)
92 /* 0x11=control frame 0x30=data frame */
93 guint info_type
= pntohs(extra_info
);
94 /* 1=FDD, 2=TDD 3.84, 3=TDD 1.28 */
95 guchar radio_mode
= extra_info
[14];
96 guchar channel_type
= 0;
99 if (!p_fp_info
|| length
< 22)
102 /* Store division type */
103 p_fp_info
->division
= (enum division_type
)radio_mode
;
105 /* Format used by K15, later fields are shifted by 8 bytes. */
106 if (pntohs(extra_info
+2) == 5)
109 p_fp_info
->iface_type
= IuB_Interface
;
111 p_fp_info
->release
= 0; /* dummy */
112 p_fp_info
->release_year
= 0; /* dummy */
113 p_fp_info
->release_month
= 0; /* dummy */
116 if (extra_info
[15] == 1)
117 p_fp_info
->is_uplink
= 1;
119 p_fp_info
->is_uplink
= 0;
121 if (info_type
== 0x11) /* control frame */
122 channel_type
= extra_info
[21 + adj
];
123 else if (info_type
== 0x30) /* data frame */
124 channel_type
= extra_info
[22 + adj
];
126 switch (channel_type
) {
128 p_fp_info
->channel
= CHANNEL_BCH
;
131 p_fp_info
->channel
= CHANNEL_PCH
;
132 p_fp_info
->paging_indications
= 0; /* dummy */
135 p_fp_info
->channel
= CHANNEL_CPCH
;
139 p_fp_info
->channel
= CHANNEL_RACH_FDD
;
140 else if (radio_mode
== 2)
141 p_fp_info
->channel
= CHANNEL_RACH_TDD
;
143 p_fp_info
->channel
= CHANNEL_RACH_TDD_128
;
147 p_fp_info
->channel
= CHANNEL_FACH_FDD
;
149 p_fp_info
->channel
= CHANNEL_FACH_TDD
;
153 p_fp_info
->channel
= CHANNEL_USCH_TDD_384
;
155 p_fp_info
->channel
= CHANNEL_USCH_TDD_128
;
159 p_fp_info
->channel
= CHANNEL_DSCH_FDD
;
161 p_fp_info
->channel
= CHANNEL_DSCH_TDD
;
164 p_fp_info
->channel
= CHANNEL_DCH
;
168 p_fp_info
->dch_crc_present
= 2; /* information not available */
170 if (info_type
== 0x30) { /* data frame */
171 p_fp_info
->num_chans
= extra_info
[23 + adj
];
172 /* For each channel */
173 for (i
= 0; i
< (guint
)p_fp_info
->num_chans
&& (36+i
*104+adj
) <= length
; ++i
) {
175 p_fp_info
->chan_tf_size
[i
] = pntohl(extra_info
+28+i
*104+adj
);
176 if (p_fp_info
->chan_tf_size
[i
])
177 /* Work out number of TBs on this channel */
178 p_fp_info
->chan_num_tbs
[i
] = pntohl(extra_info
+32+i
*104+adj
)
179 / p_fp_info
->chan_tf_size
[i
];
185 dissect_k12(tvbuff_t
* tvb
,packet_info
* pinfo
,proto_tree
* tree
)
187 static dissector_handle_t data_handles
[] = {NULL
,NULL
};
188 proto_item
* k12_item
;
189 proto_tree
* k12_tree
;
190 proto_item
* stack_item
;
191 dissector_handle_t sub_handle
= NULL
;
192 dissector_handle_t
* handles
;
195 k12_item
= proto_tree_add_protocol_format(tree
, proto_k12
, tvb
, 0, 0,
196 "Packet from: '%s' (0x%.8x)",
197 pinfo
->pseudo_header
->k12
.input_name
,
198 pinfo
->pseudo_header
->k12
.input
);
200 k12_tree
= proto_item_add_subtree(k12_item
, ett_k12
);
202 proto_tree_add_uint(k12_tree
, hf_k12_port_id
, tvb
, 0,0,pinfo
->pseudo_header
->k12
.input
);
203 proto_tree_add_string(k12_tree
, hf_k12_port_name
, tvb
, 0,0,pinfo
->pseudo_header
->k12
.input_name
);
204 stack_item
= proto_tree_add_string(k12_tree
, hf_k12_stack_file
, tvb
, 0,0,pinfo
->pseudo_header
->k12
.stack_file
);
206 k12_item
= proto_tree_add_uint(k12_tree
, hf_k12_port_type
, tvb
, 0, 0,
207 pinfo
->pseudo_header
->k12
.input_type
);
209 k12_tree
= proto_item_add_subtree(k12_item
, ett_port
);
211 switch ( pinfo
->pseudo_header
->k12
.input_type
) {
213 proto_tree_add_uint(k12_tree
, hf_k12_ts
, tvb
, 0,0,pinfo
->pseudo_header
->k12
.input_info
.ds0mask
);
215 case K12_PORT_ATMPVC
:
217 gchar
* circuit_str
= wmem_strdup_printf(wmem_packet_scope(), "%u:%u:%u",
218 (guint
)pinfo
->pseudo_header
->k12
.input_info
.atm
.vp
,
219 (guint
)pinfo
->pseudo_header
->k12
.input_info
.atm
.vc
,
220 (guint
)pinfo
->pseudo_header
->k12
.input_info
.atm
.cid
);
223 * XXX: this is prone to collisions!
224 * we need an uniform way to manage circuits between dissectors
226 pinfo
->circuit_id
= g_str_hash(circuit_str
);
228 proto_tree_add_uint(k12_tree
, hf_k12_atm_vp
, tvb
, 0, 0,
229 pinfo
->pseudo_header
->k12
.input_info
.atm
.vp
);
230 proto_tree_add_uint(k12_tree
, hf_k12_atm_vc
, tvb
, 0, 0,
231 pinfo
->pseudo_header
->k12
.input_info
.atm
.vc
);
232 if (pinfo
->pseudo_header
->k12
.input_info
.atm
.cid
)
233 proto_tree_add_uint(k12_tree
, hf_k12_atm_cid
, tvb
, 0, 0,
234 pinfo
->pseudo_header
->k12
.input_info
.atm
.cid
);
241 handles
= (dissector_handle_t
*)wmem_tree_lookup32(port_handles
, pinfo
->pseudo_header
->k12
.input
);
244 for (i
=0 ; i
< nk12_handles
; i
++) {
245 if ( epan_strcasestr(pinfo
->pseudo_header
->k12
.stack_file
, k12_handles
[i
].match
)
246 || epan_strcasestr(pinfo
->pseudo_header
->k12
.input_name
, k12_handles
[i
].match
) ) {
247 handles
= k12_handles
[i
].handles
;
253 data_handles
[0] = data_handle
;
254 handles
= data_handles
;
257 wmem_tree_insert32(port_handles
, pinfo
->pseudo_header
->k12
.input
, handles
);
261 if (handles
== data_handles
) {
262 proto_tree
* stack_tree
= proto_item_add_subtree(stack_item
, ett_stack_item
);
265 expert_add_info(pinfo
, stack_item
, &ei_k12_unmatched_stk_file
);
267 item
= proto_tree_add_text(stack_tree
,tvb
,0,0,
268 "Info: You can edit the 'K12 Protocols' table from Preferences->Protocols->k12xx");
269 PROTO_ITEM_SET_GENERATED(item
);
271 call_dissector(data_handle
, tvb
, pinfo
, tree
);
275 /* Setup subdissector information */
277 for (i
= 0; handles
[i
] && handles
[i
+1]; ++i
) {
278 if (handles
[i
] == sscop_handle
) {
279 sscop_payload_info
*p_sscop_info
= (sscop_payload_info
*)p_get_proto_data(pinfo
->fd
, proto_sscop
, 0);
281 p_sscop_info
= wmem_new0(wmem_file_scope(), sscop_payload_info
);
282 p_add_proto_data(pinfo
->fd
, proto_sscop
, 0, p_sscop_info
);
283 p_sscop_info
->subdissector
= handles
[i
+1];
286 /* Add more protocols here */
289 sub_handle
= handles
[0];
291 /* Setup information required by certain protocols */
292 if (sub_handle
== fp_handle
) {
293 fp_info
*p_fp_info
= (fp_info
*)p_get_proto_data(pinfo
->fd
, proto_fp
, 0);
295 p_fp_info
= wmem_new0(wmem_file_scope(), fp_info
);
296 p_add_proto_data(pinfo
->fd
, proto_fp
, 0, p_fp_info
);
298 fill_fp_info(p_fp_info
,
299 pinfo
->pseudo_header
->k12
.extra_info
,
300 pinfo
->pseudo_header
->k12
.extra_length
);
304 call_dissector(sub_handle
, tvb
, pinfo
, tree
);
308 k12_update_cb(void* r
, const char** err
)
310 k12_handles_t
* h
= (k12_handles_t
*)r
;
314 protos
= g_strsplit(h
->protos
,":",0);
316 for (num_protos
= 0; protos
[num_protos
]; num_protos
++)
317 g_strstrip(protos
[num_protos
]);
320 h
->handles
= (dissector_handle_t
*)g_malloc0(sizeof(dissector_handle_t
)*(num_protos
< 2 ? 2 : num_protos
));
322 for (i
= 0; i
< num_protos
; i
++) {
323 if ( ! (h
->handles
[i
] = find_dissector(protos
[i
])) ) {
324 h
->handles
[i
] = data_handle
;
326 *err
= g_strdup_printf("Could not find dissector for: '%s'",protos
[i
]);
336 k12_copy_cb(void* dest
, const void* orig
, size_t len _U_
)
338 k12_handles_t
* d
= (k12_handles_t
*)dest
;
339 const k12_handles_t
* o
= (const k12_handles_t
*)orig
;
340 gchar
** protos
= ep_strsplit(d
->protos
,":",0);
343 for (num_protos
= 0; protos
[num_protos
]; num_protos
++)
344 g_strstrip(protos
[num_protos
]);
346 d
->match
= g_strdup(o
->match
);
347 d
->protos
= g_strdup(o
->protos
);
348 d
->handles
= (dissector_handle_t
*)g_memdup(o
->handles
,(guint
)(sizeof(dissector_handle_t
)*(num_protos
+1)));
356 k12_handles_t
* h
= (k12_handles_t
*)r
;
365 protos_chk_cb(void* r _U_
, const char* p
, guint len
, const void* u1 _U_
, const void* u2 _U_
, const char** err
)
368 gchar
* line
= ep_strndup(p
,len
);
372 ascii_strdown_inplace(line
);
374 protos
= ep_strsplit(line
,":",0);
376 for (num_protos
= 0; protos
[num_protos
]; num_protos
++)
377 g_strstrip(protos
[num_protos
]);
380 *err
= ep_strdup_printf("No protocols given");
384 for (i
= 0; i
< num_protos
; i
++) {
385 if (!find_dissector(protos
[i
])) {
386 *err
= ep_strdup_printf("Could not find dissector for: '%s'",protos
[i
]);
394 UAT_CSTRING_CB_DEF(k12
,match
,k12_handles_t
)
395 UAT_CSTRING_CB_DEF(k12
,protos
,k12_handles_t
)
397 /* Make sure handles for various protocols are initialized */
399 initialize_handles_once(void)
401 static gboolean initialized
= FALSE
;
403 k12_handle
= find_dissector("k12");
404 data_handle
= find_dissector("data");
405 sscop_handle
= find_dissector("sscop");
406 fp_handle
= find_dissector("fp");
411 void proto_reg_handoff_k12(void)
413 initialize_handles_once();
414 dissector_add_uint("wtap_encap", WTAP_ENCAP_K12
, k12_handle
);
418 proto_register_k12(void)
420 static hf_register_info hf
[] = {
421 { &hf_k12_port_id
, { "Port Id", "k12.port_id", FT_UINT32
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
422 { &hf_k12_port_name
, { "Port Name", "k12.port_name", FT_STRING
, BASE_NONE
, NULL
, 0x0,NULL
, HFILL
}},
423 { &hf_k12_stack_file
, { "Stack file used", "k12.stack_file", FT_STRING
, BASE_NONE
, NULL
, 0x0,NULL
, HFILL
}},
424 { &hf_k12_port_type
, { "Port type", "k12.input_type", FT_UINT32
, BASE_HEX
, VALS(k12_port_types
), 0x0,NULL
, HFILL
}},
425 { &hf_k12_ts
, { "Timeslot mask", "k12.ds0.ts", FT_UINT32
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
426 { &hf_k12_atm_vp
, { "ATM VPI", "atm.vpi", FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
427 { &hf_k12_atm_vc
, { "ATM VCI", "atm.vci", FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
428 { &hf_k12_atm_cid
, { "AAL2 CID", "aal2.cid", FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}}
431 static gint
*ett
[] = {
437 static ei_register_info ei
[] = {
438 { &ei_k12_unmatched_stk_file
, { "k12.unmatched_stk_file", PI_UNDECODED
, PI_WARN
, "Warning: stk file not matched in the 'K12 Protocols' table", EXPFILL
}},
441 static uat_field_t uat_k12_flds
[] = {
442 UAT_FLD_CSTRING_ISPRINT(k12
,match
,"Match string",
443 "A string that will be matched (a=A) against an .stk filename or the name of a port.\n"
444 "The first match wins, the order of entries in the table is important!."),
445 UAT_FLD_CSTRING_OTHER(k12
,protos
,"Protocol",protos_chk_cb
,
446 "The lowest layer protocol described by this .stk file (eg: mtp2).\n"
447 "Use (sscop:sscf-nni) for sscf-nni (MTP3b) with sscop"),
451 module_t
*k12_module
;
452 expert_module_t
* expert_k12
;
454 proto_k12
= proto_register_protocol("K12xx", "K12xx", "k12");
455 proto_register_field_array(proto_k12
, hf
, array_length(hf
));
456 proto_register_subtree_array(ett
, array_length(ett
));
457 expert_k12
= expert_register_protocol(proto_k12
);
458 expert_register_field_array(expert_k12
, ei
, array_length(ei
));
459 register_dissector("k12", dissect_k12
, proto_k12
);
461 k12_uat
= uat_new("K12 Protocols",
462 sizeof(k12_handles_t
),
463 "k12_protos", /* filename */
464 TRUE
, /* from_profile */
465 (void**) &k12_handles
, /* data_ptr */
466 &nk12_handles
, /* numitems_ptr */
467 UAT_AFFECTS_DISSECTION
, /* affects dissection of packets, but not set of named fields */
468 "ChK12ProtocolsSection", /* help */
475 k12_module
= prefs_register_protocol(proto_k12
, NULL
);
477 prefs_register_obsolete_preference(k12_module
, "config");
479 prefs_register_uat_preference(k12_module
, "cfg",
481 "A table of matches vs stack filenames and relative protocols",
484 port_handles
= wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());