octsdr-2g-wireshark/application/tool/wireshark/plugins/octasic/octsdr/octvc1/source/octvc1_plugin.c

405 lines
13 KiB
C

/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
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 <http://www.gnu.org/licenses/>.
Release: Octasic Application Development Framework OCTADF-01.00.01-B497 (2014/01/09)
$Octasic_Revision: $
\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#include <string.h>
#include <config.h>
#include <epan/packet.h>
#include <epan/prefs.h>
#include <epan/expert.h>
#include "../include/plugin_info.h"
#include "../include/module.h"
#define OCT_DECLARE_COMMON
#include "../include/octvc1_common.h"
#include <gsm/octvc1_gsm_api.h>
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");
}