2014-02-09 17:01:41 +00:00
/* packet-logcat.c
* Routines for Android Logcat binary format v1 and v2
*
* Copyright 2014 , Michal Labedzki for Tieto Corporation
*
* Wireshark - Network traffic analyzer
* By Gerald Combs < gerald @ wireshark . org >
* Copyright 1998 Gerald Combs
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation ; either version 2
* of the License , or ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA .
*/
# include "config.h"
# include <epan/packet.h>
# include <epan/expert.h>
2014-02-09 17:35:08 +00:00
# include <epan/exported_pdu.h>
# include <epan/tap.h>
2015-03-01 17:08:20 +00:00
# include <epan/prefs.h>
2014-02-09 17:37:44 +00:00
# include <wiretap/wtap.h>
2014-02-09 17:01:41 +00:00
static int proto_logcat = - 1 ;
static int hf_logcat_version = - 1 ;
static int hf_logcat_length = - 1 ;
static int hf_logcat_padding = - 1 ;
static int hf_logcat_header_size = - 1 ;
static int hf_logcat_pid = - 1 ;
static int hf_logcat_tid = - 1 ;
static int hf_logcat_timestamp = - 1 ;
static int hf_logcat_timestamp_seconds = - 1 ;
static int hf_logcat_timestamp_nanoseconds = - 1 ;
static int hf_logcat_euid = - 1 ;
static int hf_logcat_priority = - 1 ;
static int hf_logcat_tag = - 1 ;
static int hf_logcat_log = - 1 ;
static gint ett_logcat = - 1 ;
static gint ett_logcat_timestamp = - 1 ;
2014-06-22 12:47:02 +00:00
static gint ett_logcat_log = - 1 ;
2014-02-09 17:01:41 +00:00
static dissector_handle_t logcat_handle ;
2014-06-22 12:47:02 +00:00
static dissector_handle_t data_text_lines_handle ;
2014-02-09 17:01:41 +00:00
2014-02-09 17:35:08 +00:00
static gint exported_pdu_tap = - 1 ;
2014-02-09 17:01:41 +00:00
static expert_field ei_invalid_payload_length = EI_INIT ;
2015-03-01 17:08:20 +00:00
static gboolean pref_one_line_info_column = TRUE ;
2014-05-14 07:45:23 +00:00
const value_string priority_vals [ ] = {
2014-02-09 17:01:41 +00:00
{ 0x00 , " Unknown " } ,
{ 0x01 , " Default " } ,
{ 0x02 , " Verbose " } ,
{ 0x03 , " Debug " } ,
{ 0x04 , " Info " } ,
{ 0x05 , " Warning " } ,
{ 0x06 , " Error " } ,
{ 0x07 , " Fatal " } ,
{ 0x08 , " Silent " } ,
{ 0 , NULL }
} ;
void proto_register_logcat ( void ) ;
void proto_reg_handoff_logcat ( void ) ;
static gint detect_version ( tvbuff_t * tvb , gint offset ) {
guint16 payload_length ;
guint16 try_header_size ;
2014-08-05 16:35:36 +00:00
payload_length = tvb_get_letohs ( tvb , offset ) ;
2014-02-09 17:01:41 +00:00
try_header_size = tvb_get_letohs ( tvb , offset + 2 ) ;
2015-11-30 16:26:30 +00:00
if ( try_header_size ! = 24 )
2014-02-09 17:01:41 +00:00
return 1 ;
if ( tvb_reported_length_remaining ( tvb , offset + 24 + payload_length ) > = 0 )
return 2 ;
return 1 ;
}
static int
dissect_logcat ( tvbuff_t * tvb , packet_info * pinfo , proto_tree * tree , void * data _U_ )
{
gint offset = 0 ;
proto_tree * maintree ;
proto_item * mainitem ;
proto_tree * subtree ;
proto_item * subitem ;
guint16 length ;
guint16 check_length ;
guint32 string_length ;
gint logger_version ;
guint8 * log ;
gchar * c ;
2014-06-22 12:47:02 +00:00
tvbuff_t * next_tvb ;
2014-02-09 17:01:41 +00:00
col_set_str ( pinfo - > cinfo , COL_PROTOCOL , " Logcat " ) ;
2014-08-05 16:35:36 +00:00
col_clear ( pinfo - > cinfo , COL_INFO ) ;
2014-02-09 17:01:41 +00:00
mainitem = proto_tree_add_item ( tree , proto_logcat , tvb , offset , - 1 , ENC_NA ) ;
maintree = proto_item_add_subtree ( mainitem , ett_logcat ) ;
logger_version = detect_version ( tvb , offset ) ;
subitem = proto_tree_add_uint ( maintree , hf_logcat_version , tvb , offset , 0 , logger_version ) ;
PROTO_ITEM_SET_GENERATED ( subitem ) ;
proto_tree_add_item ( maintree , hf_logcat_length , tvb , offset , 2 , ENC_LITTLE_ENDIAN ) ;
length = tvb_get_letohs ( tvb , offset ) ;
offset + = 2 ;
if ( logger_version = = 1 ) {
proto_tree_add_item ( maintree , hf_logcat_padding , tvb , offset , 2 , ENC_LITTLE_ENDIAN ) ;
} else {
proto_tree_add_item ( maintree , hf_logcat_header_size , tvb , offset , 2 , ENC_LITTLE_ENDIAN ) ;
}
offset + = 2 ;
proto_tree_add_item ( maintree , hf_logcat_pid , tvb , offset , 4 , ENC_LITTLE_ENDIAN ) ;
offset + = 4 ;
proto_tree_add_item ( maintree , hf_logcat_tid , tvb , offset , 4 , ENC_LITTLE_ENDIAN ) ;
offset + = 4 ;
subitem = proto_tree_add_item ( maintree , hf_logcat_timestamp , tvb , offset , 8 , ENC_LITTLE_ENDIAN ) ;
subtree = proto_item_add_subtree ( subitem , ett_logcat_timestamp ) ;
proto_tree_add_item ( subtree , hf_logcat_timestamp_seconds , tvb , offset , 4 , ENC_LITTLE_ENDIAN ) ;
offset + = 4 ;
proto_tree_add_item ( subtree , hf_logcat_timestamp_nanoseconds , tvb , offset , 4 , ENC_LITTLE_ENDIAN ) ;
offset + = 4 ;
if ( logger_version > = 2 ) {
proto_tree_add_item ( maintree , hf_logcat_euid , tvb , offset , 4 , ENC_LITTLE_ENDIAN ) ;
offset + = 4 ;
}
/* payload */
proto_tree_add_item ( maintree , hf_logcat_priority , tvb , offset , 1 , ENC_LITTLE_ENDIAN ) ;
offset + = 1 ;
check_length = 1 ;
string_length = tvb_strsize ( tvb , offset ) ;
2016-05-29 09:10:24 +00:00
proto_tree_add_item ( maintree , hf_logcat_tag , tvb , offset , string_length , ENC_UTF_8 | ENC_NA ) ;
2014-02-09 17:01:41 +00:00
2015-10-29 03:12:53 +00:00
set_address_tvb ( & pinfo - > src , AT_STRINGZ , string_length + 1 , tvb , offset ) ;
2015-10-21 19:04:16 +00:00
set_address ( & pinfo - > dst , AT_STRINGZ , 7 , " Logcat " ) ;
2014-02-09 17:01:41 +00:00
offset + = string_length ;
check_length + = string_length ;
string_length = length - string_length - 1 ;
2016-05-29 09:10:24 +00:00
log = tvb_get_string_enc ( wmem_packet_scope ( ) , tvb , offset , string_length , ENC_UTF_8 ) ;
2014-02-09 17:01:41 +00:00
/* New line characters convert to spaces to ensure column Info display one line */
2015-03-01 17:08:20 +00:00
if ( pref_one_line_info_column ) {
2014-02-09 17:01:41 +00:00
while ( ( c = g_utf8_strchr ( log , string_length , ' \n ' ) ) )
* c = ' ' ;
while ( ( c = g_utf8_strchr ( log , string_length , ' \r ' ) ) )
* c = ' ' ;
2015-03-01 17:08:20 +00:00
}
2014-02-09 17:01:41 +00:00
2016-05-29 09:10:24 +00:00
subitem = proto_tree_add_item ( maintree , hf_logcat_log , tvb , offset , string_length , ENC_UTF_8 | ENC_NA ) ;
2014-06-22 12:47:02 +00:00
subtree = proto_item_add_subtree ( subitem , ett_logcat_log ) ;
next_tvb = tvb_new_subset_length ( tvb , offset , string_length - 1 ) ;
call_dissector ( data_text_lines_handle , next_tvb , pinfo , subtree ) ;
2014-02-09 17:01:41 +00:00
col_add_str ( pinfo - > cinfo , COL_INFO , log ) ;
offset + = string_length ;
check_length + = string_length ;
if ( length ! = check_length )
2014-08-05 16:35:36 +00:00
proto_tree_add_expert ( maintree , pinfo , & ei_invalid_payload_length , tvb , offset , tvb_reported_length_remaining ( tvb , offset ) ) ;
2014-02-09 17:01:41 +00:00
2014-02-09 17:35:08 +00:00
if ( have_tap_listener ( exported_pdu_tap ) ) {
2016-06-24 03:10:08 +00:00
exp_pdu_data_t * exp_pdu_data = export_pdu_create_tags ( pinfo , " logcat " , EXP_PDU_TAG_PROTO_NAME , NULL ) ;
2014-03-18 22:01:22 +00:00
exp_pdu_data - > tvb_captured_length = tvb_captured_length ( tvb ) ;
exp_pdu_data - > tvb_reported_length = tvb_reported_length ( tvb ) ;
2014-02-09 17:35:08 +00:00
exp_pdu_data - > pdu_tvb = tvb ;
tap_queue_packet ( exported_pdu_tap , pinfo , exp_pdu_data ) ;
}
2014-02-09 17:01:41 +00:00
return offset ;
}
void
proto_register_logcat ( void )
{
2015-03-01 17:08:20 +00:00
module_t * module ;
2014-02-09 17:01:41 +00:00
expert_module_t * expert_module ;
static hf_register_info hf [ ] = {
{ & hf_logcat_version ,
{ " Logger Version " , " logcat.logger_version " ,
FT_UINT8 , BASE_DEC , NULL , 0x00 ,
NULL , HFILL }
} ,
{ & hf_logcat_length ,
{ " Payload Length " , " logcat.length " ,
FT_UINT16 , BASE_DEC , NULL , 0x00 ,
" Payload start after nanoseconds or euid " , HFILL }
} ,
{ & hf_logcat_padding ,
{ " Padding " , " logcat.padding " ,
FT_UINT16 , BASE_HEX , NULL , 0x00 ,
" No matter what, we get 2 bytes of padding " , HFILL }
} ,
{ & hf_logcat_header_size ,
{ " Header Size " , " logcat.header_size " ,
FT_UINT16 , BASE_HEX , NULL , 0x00 ,
" Size of struct logger_entry_v2 " , HFILL }
} ,
{ & hf_logcat_pid ,
{ " PID " , " logcat.pid " ,
FT_INT32 , BASE_DEC , NULL , 0x00 ,
" Process ID " , HFILL }
} ,
{ & hf_logcat_tid ,
{ " TID " , " logcat.tid " ,
FT_INT32 , BASE_DEC , NULL , 0x00 ,
" Thread ID " , HFILL }
} ,
{ & hf_logcat_timestamp ,
{ " Timestamp " , " logcat.timestamp " ,
FT_ABSOLUTE_TIME , ABSOLUTE_TIME_LOCAL , NULL , 0x00 ,
NULL , HFILL }
} ,
{ & hf_logcat_timestamp_seconds ,
{ " Timestamp in seconds " , " logcat.timestamp.seconds " ,
FT_INT32 , BASE_DEC , NULL , 0x00 ,
NULL , HFILL }
} ,
{ & hf_logcat_timestamp_nanoseconds ,
{ " Nanoseconds Timestamp " , " logcat.timestamp.nanoseconds " ,
FT_INT32 , BASE_DEC , NULL , 0x00 ,
NULL , HFILL }
} ,
{ & hf_logcat_euid ,
{ " EUID " , " logcat.euid " ,
FT_UINT32 , BASE_DEC , NULL , 0x00 ,
" Effective UID of logger " , HFILL }
} ,
{ & hf_logcat_priority ,
{ " Priority " , " logcat.priority " ,
FT_UINT8 , BASE_DEC , VALS ( priority_vals ) , 0x00 ,
NULL , HFILL }
} ,
{ & hf_logcat_tag ,
{ " Tag " , " logcat.tag " ,
2016-05-29 09:10:24 +00:00
FT_STRINGZ , STR_UNICODE , NULL , 0x00 ,
2014-02-09 17:01:41 +00:00
NULL , HFILL }
} ,
{ & hf_logcat_log ,
{ " Log " , " logcat.log " ,
2016-05-29 09:10:24 +00:00
FT_STRINGZ , STR_UNICODE , NULL , 0x00 ,
2014-02-09 17:01:41 +00:00
NULL , HFILL }
}
} ;
static gint * ett [ ] = {
& ett_logcat ,
2014-06-22 12:47:02 +00:00
& ett_logcat_timestamp ,
& ett_logcat_log
2014-02-09 17:01:41 +00:00
} ;
static ei_register_info ei [ ] = {
{ & ei_invalid_payload_length , { " logcat.expert.invalid_payload_length " , PI_PROTOCOL , PI_WARN , " Payload length does not meet sum of payload data length " , EXPFILL } } ,
} ;
proto_logcat = proto_register_protocol ( " Android Logcat " , " Logcat " , " logcat " ) ;
proto_register_field_array ( proto_logcat , hf , array_length ( hf ) ) ;
proto_register_subtree_array ( ett , array_length ( ett ) ) ;
2015-12-09 04:04:01 +00:00
logcat_handle = register_dissector ( " logcat " , dissect_logcat , proto_logcat ) ;
2014-02-09 17:01:41 +00:00
expert_module = expert_register_protocol ( proto_logcat ) ;
expert_register_field_array ( expert_module , ei , array_length ( ei ) ) ;
2014-06-19 00:42:47 +00:00
exported_pdu_tap = register_export_pdu_tap ( " Logcat " ) ;
2015-03-01 17:08:20 +00:00
module = prefs_register_protocol ( proto_logcat , NULL ) ;
prefs_register_bool_preference ( module , " oneline_info_column " ,
" Use oneline info column " ,
2015-03-05 10:05:07 +00:00
" Use oneline info column by replace all new line characters by spaces " ,
2015-03-01 17:08:20 +00:00
& pref_one_line_info_column ) ;
2014-02-09 17:01:41 +00:00
}
void
proto_reg_handoff_logcat ( void )
{
2016-03-16 13:02:52 +00:00
data_text_lines_handle = find_dissector_add_dependency ( " data-text-lines " , proto_logcat ) ;
2014-06-22 12:47:02 +00:00
2014-02-09 17:37:44 +00:00
dissector_add_uint ( " wtap_encap " , WTAP_ENCAP_LOGCAT , logcat_handle ) ;
2014-06-20 16:43:28 +00:00
dissector_add_for_decode_as ( " tcp.port " , logcat_handle ) ;
2014-02-09 17:01:41 +00:00
}
/*
* Editor modelines - http : //www.wireshark.org/tools/modelines.html
*
* Local variables :
* c - basic - offset : 4
* tab - width : 8
* indent - tabs - mode : nil
* End :
*
* vi : set shiftwidth = 4 tabstop = 8 expandtab :
* : indentSize = 4 : tabSize = 8 : noTabs = true :
*/