/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ File: octvc1_plugin.c Copyright (c) 2014 Octasic Inc. All rights reserved. Description: This program is free software; you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation; either version 3 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 Affero General Public License along with this program. If not, see . Release: Octasic Application Development Framework OCTADF-01.00.01-B497 (2014/01/09) $Octasic_Revision: $ \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ #include #include #include #include #include #include "../include/plugin_info.h" #include "../include/module.h" #define OCT_DECLARE_COMMON #include "../include/octvc1_common.h" #include static int proto_octvc1 = -1; static int fUserRegistered = 0; char * pszOctvc1_user_name=NULL; char * pszOctvc1_user_id=NULL; int g_fIsRegistered = 0; static char l_szRegisteredUser[128]={0}; static int l_iRegisteredUserLen = 0; static int l_id_code_Registered = 0; static gchar l_szAPIStr[256]; static int l_fIsGod = 0; dissector_handle_t data_handle; const gchar* octvc1_chck_private( guint32 f_id_code, const value_string *f_PrivateApi, gint32 *f_piRegistered ) { const gchar* pszValueString; //CHck if same as last request if( l_iRegisteredUserLen && ( l_id_code_Registered == f_id_code ) ) { *f_piRegistered = 1; return l_szAPIStr; } *f_piRegistered = 0; pszValueString = val_to_str( f_id_code, f_PrivateApi, cOCTVC1_UNKNOWN_STRING ); if( strcmp( pszValueString, cOCTVC1_UNKNOWN_STRING ) ) { // Expect API ID STRING:user,user2,user3 gchar *pszColumn = strchr( pszValueString, ':' ); if( pszColumn ) { gchar *pszStr; // Keep API string strncpy( l_szAPIStr, pszValueString, (pszColumn-pszValueString) ); l_szAPIStr[(pszColumn-pszValueString)]=0; // Chck if god is register if( !l_fIsGod ) pszStr = strstr( pszColumn+1, l_szRegisteredUser ); // Find if register for this if( l_fIsGod || ( pszStr && ((pszStr==(pszColumn+1)) || (*(pszStr-1)==',') ) && ( (*(pszStr+l_iRegisteredUserLen)==',') || (*(pszStr+l_iRegisteredUserLen)==0 ) ) ) ) { l_id_code_Registered = f_id_code; *f_piRegistered = 1; return l_szAPIStr; } } } return cOCTVC1_UNKNOWN_STRING; } void pref_proto_octvc1_apply_callback( void ) { char *pszPath; // by default this callback is called at startup ... skip the first call if( fUserRegistered ) { int fReguser=0; if( ( strcmp( pszOctvc1_user_name, cOCTVC1_GOD_USER ) == 0 ) && ( strcmp( pszOctvc1_user_id, cOCTVC1_GOD_USER_ID ) == 0 ) ) { fReguser = 1; l_fIsGod = 1; } else { int i; for( i=0; ; i++ ) { if( aOCTVC1_user_list[i][0] == NULL ) break; if( ( strcmp( aOCTVC1_user_list[i][0], pszOctvc1_user_name ) == 0 ) && ( strcmp( aOCTVC1_user_list[i][1], pszOctvc1_user_id ) == 0 ) ) { fReguser = 1; l_fIsGod = 0; break; } } } if( fReguser ) { g_fIsRegistered = 1; strcpy( l_szRegisteredUser, pszOctvc1_user_name ); l_iRegisteredUserLen = strlen( l_szRegisteredUser ); } else { g_fIsRegistered = 0; l_fIsGod = 0; } } fUserRegistered = 1; prefs_set_pref( "octvc1.user_name:user" ); prefs_set_pref( "octvc1.user_id:****" ); write_prefs( &pszPath ); // Reset last check l_id_code_Registered = 0; l_szAPIStr[0] = 0; } extern tModuleColInfo aOCTVC1ModuleColInfo[]; #define mWD_OCTVC1_CID_CODE(uint32) ((uint32) & 0x00000FFF) void dissect_OCTVC1_GSM(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { int temp_data, ulMsgType, ulCommandId, ulOctvc1MsgType, remaining_length, module_index; int offset = 0; tvbuff_t *message_tvb; const gchar* pszValueString = NULL; tModuleColInfo GsmModule; /* Find Tbl Module Index */ match_strval_idx( cOCTVC1_GSM_UID, vals_OCTVC1_module_UID, &module_index ); /*Get the proper module info */ GsmModule = aOCTVC1ModuleColInfo[module_index]; temp_data = tvb_get_ntohs( tvb, offset ); proto_tree_add_text(tree, tvb, offset, 2, "reserved %d", temp_data ); offset += 2; ulMsgType = tvb_get_guint8( tvb, offset ); ulCommandId = (ulMsgType & 0x7F) | cOCTVC1_GSM_CID_BASE; ulOctvc1MsgType = ((ulMsgType & 0x80) == 0 )? cOCTVC1_MSG_TYPE_RESPONSE: cOCTVC1_MSG_TYPE_COMMAND; /* Hardcoded event mapping */ if( ulMsgType == 0x01 || ulMsgType == 0x02 || ulMsgType == 0x07 || ulMsgType == 0x0e || ulMsgType == 0x16 ) { ulOctvc1MsgType = cOCTVC1_MSG_TYPE_NOTIFICATION; ulCommandId = ulMsgType | cOCTVC1_GSM_EID_BASE; } proto_tree_add_text(tree, tvb, offset, 1, "MsgType 0x%02x (CID:0x%08x, type:%d)", ulMsgType, ulCommandId, ulOctvc1MsgType ); offset += 1; temp_data = tvb_get_guint8( tvb, offset ); proto_tree_add_text(tree, tvb, offset, 1, "size: %d", temp_data ); offset += 1; temp_data = tvb_get_ntohs( tvb, offset ); proto_tree_add_text(tree, tvb, offset, 2, "sequence %d", temp_data ); offset += 2; if( (ulMsgType & 0x7F) == 0x00 ) { ulCommandId |= 0x100; } /*API is not orthogonal!! remap response to proper Ids */ if( ulOctvc1MsgType == cOCTVC1_MSG_TYPE_RESPONSE ) { if( ulMsgType == 0x08 || ulMsgType == 0x09 ) ulCommandId = ((ulMsgType-1) & 0x7F) | cOCTVC1_GSM_CID_BASE; if( ulMsgType == 0x0a ) ulCommandId = (0x11) | cOCTVC1_GSM_CID_BASE; } if( ulOctvc1MsgType == cOCTVC1_MSG_TYPE_COMMAND ) { if( ulMsgType == 0x82 || ulMsgType == 0x81 ) ulCommandId |= cOCTVC1_MSG_NO_RESPONSE_FLAG; } if( ulOctvc1MsgType == cOCTVC1_MSG_TYPE_NOTIFICATION ) { pszValueString = val_to_str( mWD_OCTVC1_CID_CODE( ulCommandId), GsmModule.apEvtIdValueString, cOCTVC1_UNKNOWN_STRING ); }else { pszValueString = val_to_str( mWD_OCTVC1_CID_CODE( ulCommandId), GsmModule.apCodeIdValueString, cOCTVC1_UNKNOWN_STRING ); } if ( check_col(pinfo->cinfo, COL_INFO) ) { col_add_fstr( pinfo->cinfo, COL_INFO, "%s_MSG_%s(0x%04X)", GsmModule.pszModuleName, pszValueString, ulCommandId ); } if ( check_col(pinfo->cinfo, COL_PROTOCOL) ) col_set_str(pinfo->cinfo, COL_PROTOCOL, "oct_gsm"); remaining_length = tvb_reported_length_remaining(tvb, offset); message_tvb = tvb_new_subset(tvb, offset, remaining_length, remaining_length); GsmModule.Dissector_fnc( ulOctvc1MsgType, ulCommandId, message_tvb, pinfo, tree); /* We can call the amr plugin */ /* think it can support IF2 Frame (GPP TS 26.101), need to double check */ } #ifdef cOCTVC1_WCDMA_UID void dissect_OCTVC1_WCDMA(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { int temp_data, ulMsgType, ulCommandId, ulOctvc1MsgType, remaining_length, module_index; int offset = 0; tvbuff_t *message_tvb; const gchar* pszValueString = NULL; tModuleColInfo WcdmaModule; /* Find Tbl Module Index */ match_strval_idx( cOCTVC1_WCDMA_UID, vals_OCTVC1_module_UID, &module_index ); /*Get the proper module info */ WcdmaModule = aOCTVC1ModuleColInfo[module_index]; ulMsgType = 0; ulOctvc1MsgType = cOCTVC1_MSG_TYPE_COMMAND; temp_data = tvb_get_ntohs( tvb, offset ); proto_tree_add_text(tree, tvb, offset, 1, "L1c etherType 0x%02x", temp_data ); offset += 2; temp_data = tvb_get_ntohs( tvb, offset ); proto_tree_add_text(tree, tvb, offset, 1, "Body Size: %d", temp_data ); offset += 2; temp_data = tvb_get_ntohs( tvb, offset ); proto_tree_add_text(tree, tvb, offset, 2, "Message Type: %d", temp_data ); offset += 2; temp_data = tvb_get_ntohs( tvb, offset ); proto_tree_add_text(tree, tvb, offset, 2, "Message Id: %d", temp_data ); ulCommandId = (temp_data & 0x7F) | cOCTVC1_WCDMA_CID_BASE; offset += 2; temp_data = tvb_get_guint8( tvb, offset ); proto_tree_add_text(tree, tvb, offset, 2, "FP Header size: %d", temp_data ); offset += 2; temp_data = tvb_get_guint8( tvb, offset ); proto_tree_add_text(tree, tvb, offset, 2, "Transaction Id: %d", temp_data ); offset += 2; /*API is not orthogonal!! remap response to proper Ids */ if( ulOctvc1MsgType == cOCTVC1_MSG_TYPE_RESPONSE ) { if( ulMsgType == 0x08 || ulMsgType == 0x09 ) ulCommandId = ((ulMsgType-1) & 0x7F) | cOCTVC1_GSM_CID_BASE; if( ulMsgType == 0x0a ) ulCommandId = (0x11) | cOCTVC1_GSM_CID_BASE; } if( ulOctvc1MsgType == cOCTVC1_MSG_TYPE_NOTIFICATION ) { pszValueString = val_to_str( mWD_OCTVC1_CID_CODE( ulCommandId), WcdmaModule.apEvtIdValueString, cOCTVC1_UNKNOWN_STRING ); }else { pszValueString = val_to_str( mWD_OCTVC1_CID_CODE( ulCommandId), WcdmaModule.apCodeIdValueString, cOCTVC1_UNKNOWN_STRING ); } if ( check_col(pinfo->cinfo, COL_INFO) ) { col_add_fstr( pinfo->cinfo, COL_INFO, "%s_MSG_%s(0x%04X)", WcdmaModule.pszModuleName, pszValueString, ulCommandId ); } if ( check_col(pinfo->cinfo, COL_PROTOCOL) ) col_set_str(pinfo->cinfo, COL_PROTOCOL, "oct_wcdma"); remaining_length = tvb_reported_length_remaining(tvb, offset); message_tvb = tvb_new_subset(tvb, offset, remaining_length, remaining_length); WcdmaModule.Dissector_fnc( ulOctvc1MsgType, ulCommandId, message_tvb, pinfo, tree); /* We can call the amr plugin */ /* think it can support IF2 Frame (GPP TS 26.101), need to double check */ } #endif /************************************************************************* * * Code to register the protocol with Wireshark * **************************************************************************/ void proto_register_octvc1(void) { module_t *octvc1_module; int proto_gsm = -1; int proto_wcdma = -1; proto_octvc1 = proto_register_protocol( "OCTVC1 Packets", "Octasic OCTVC1", "octvc1"); octvc1_module = prefs_register_protocol(proto_octvc1, pref_proto_octvc1_apply_callback); prefs_register_string_preference(octvc1_module, "user_name", "User name", "OCTVC1 user name", &pszOctvc1_user_name); prefs_register_string_preference(octvc1_module, "user_id", "User id", "OCTVC1 user id", &pszOctvc1_user_id); /* register ctrl dissector */ proto_register_octvc1_ctrl(); /* register event dissector */ proto_register_octvc1_event(); /* Call module register fnc */ ws_register_dissector_module(); proto_gsm = proto_register_protocol( "OCTASIC GSM MODULE", "OCTGSM", "oct_gsm"); register_dissector("OCTGSM", dissect_OCTVC1_GSM, proto_gsm); #ifdef cOCTVC1_WCDMA_UID proto_wcdma = proto_register_protocol( "OCTASIC WCDMA MODULE", "OCTWCDMA", "oct_wcdma"); register_dissector("OCTWCDMA", dissect_OCTVC1_WCDMA, proto_wcdma); #endif } /************************************************************************* * * If this dissector uses sub-dissector registration add a registration routine. * This format is required because a script is used to find these routines and * create the code that calls these routines. * **************************************************************************/ void proto_reg_handoff_octvc1(void) { extern int proto_octvc1_event; extern int proto_octvc1_ctrl; extern int dissect_octvc1_ctrl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree); extern int dissect_octvc1_event(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree); dissector_handle_t octvc1_ctrl_handle; dissector_handle_t octvc1_event_handle; register_dissector_table( "vocallonet.api_type", "Vocallonet API", FT_UINT32, BASE_HEX); octvc1_ctrl_handle = new_create_dissector_handle(dissect_octvc1_ctrl, proto_octvc1_ctrl); dissector_add_uint("vocallonet.api_type", 0, octvc1_ctrl_handle); octvc1_event_handle = new_create_dissector_handle(dissect_octvc1_event, proto_octvc1_event); dissector_add_uint("vocallonet.api_type", 0, octvc1_event_handle); data_handle = find_dissector("data"); }