mirror of https://github.com/sipwise/kamailio.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
303 lines
9.1 KiB
303 lines
9.1 KiB
/*
|
|
* $Id$
|
|
*
|
|
* Copyright (C) 2012 Smile Communications, jason.penton@smilecoms.com
|
|
* Copyright (C) 2012 Smile Communications, richard.good@smilecoms.com
|
|
*
|
|
* The initial version of this code was written by Dragos Vingarzan
|
|
* (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
|
|
* Fruanhofer Institute. It was and still is maintained in a separate
|
|
* branch of the original SER. We are therefore migrating it to
|
|
* Kamailio/SR and look forward to maintaining it from here on out.
|
|
* 2011/2012 Smile Communications, Pty. Ltd.
|
|
* ported/maintained/improved by
|
|
* Jason Penton (jason(dot)penton(at)smilecoms.com and
|
|
* Richard Good (richard(dot)good(at)smilecoms.com) as part of an
|
|
* effort to add full IMS support to Kamailio/SR using a new and
|
|
* improved architecture
|
|
*
|
|
* NB: Alot of this code was originally part of OpenIMSCore,
|
|
* FhG Fokus.
|
|
* Copyright (C) 2004-2006 FhG Fokus
|
|
* Thanks for great work! This is an effort to
|
|
* break apart the various CSCF functions into logically separate
|
|
* components. We hope this will drive wider use. We also feel
|
|
* that in this way the architecture is more complete and thereby easier
|
|
* to manage in the Kamailio/SR environment
|
|
*
|
|
* This file is part of Kamailio, a free SIP server.
|
|
*
|
|
* Kamailio 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
|
|
*
|
|
* Kamailio 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 "../../timer.h"
|
|
#include "../../modules/sl/sl.h"
|
|
|
|
#include "mod.h"
|
|
#include "scscf_list.h"
|
|
#include "cxdx_uar.h"
|
|
#include "cxdx_lir.h"
|
|
#include "db.h"
|
|
#include "nds.h"
|
|
|
|
MODULE_VERSION
|
|
|
|
struct tm_binds tmb;
|
|
struct cdp_binds cdpb;
|
|
cdp_avp_bind_t *cdp_avp;
|
|
|
|
/** SL API structure */
|
|
sl_api_t slb;
|
|
|
|
|
|
//module parameters
|
|
char* ims_icscf_db_url="mysql://icscf:heslo@localhost/hssdata"; /**< DB URL */
|
|
char* ims_icscf_db_nds_table="nds_trusted_domains"; /**< NDS table in DB */
|
|
char* ims_icscf_db_scscf_table="s_cscf"; /**< S-CSCF table in db */
|
|
char* ims_icscf_db_capabilities_table="s_cscf_capabilities"; /**< S-CSCF capabilities table in db */
|
|
|
|
int ims_icscf_hash_size = 128;
|
|
int scscf_entry_expiry = 300;
|
|
|
|
/* parameters storage */
|
|
char* cxdx_dest_realm_s = "ims.smilecoms.com";
|
|
str cxdx_dest_realm;
|
|
|
|
str preferred_scscf_uri = str_init("sip:scscf.ims.smilecoms.com:4060");
|
|
int use_preferred_scscf_uri = 0;
|
|
|
|
//Only used if we want to force the Rx peer
|
|
//Usually this is configured at a stack level and the first request uses realm routing
|
|
char* cxdx_forced_peer_s = "";
|
|
str cxdx_forced_peer;
|
|
|
|
/**
|
|
* Name of the route, if a user is not found in the HSS (LIR)
|
|
*/
|
|
char* route_lir_user_unknown=0; /* default is the main route */
|
|
/**
|
|
* Number of the route, if a user is not found in the HSS (LIR)
|
|
*/
|
|
int route_lir_user_unknown_no=-1;
|
|
|
|
/**
|
|
* Name of the route, if a user is not found in the HSS (UAR)
|
|
*/
|
|
char* route_uar_user_unknown=0; /* default is the main route */
|
|
/**
|
|
* Number of the route, if a user is not found in the HSS (UAR)
|
|
*/
|
|
int route_uar_user_unknown_no=-1;
|
|
|
|
|
|
/** module functions */
|
|
static int mod_init(void);
|
|
static int fixup_uar(void** param, int param_no);
|
|
static int fixup_lir(void** param, int param_no);
|
|
|
|
static cmd_export_t cmds[] = {
|
|
{"I_perform_user_authorization_request", (cmd_function) I_perform_user_authorization_request, 2, fixup_uar, 0, REQUEST_ROUTE},
|
|
{"I_perform_location_information_request", (cmd_function) I_perform_location_information_request, 2, fixup_lir, 0, REQUEST_ROUTE},
|
|
{"I_scscf_select", (cmd_function) I_scscf_select, 1, 0, 0, REQUEST_ROUTE | FAILURE_ROUTE},
|
|
{"I_scscf_drop", (cmd_function) I_scscf_drop, 0, 0, 0, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE},
|
|
{ 0, 0, 0, 0, 0, 0}
|
|
};
|
|
|
|
static param_export_t params[] = {
|
|
{"route_lir_user_unknown", PARAM_STRING, &route_lir_user_unknown},
|
|
{"route_uar_user_unknown", PARAM_STRING, &route_uar_user_unknown},
|
|
{"scscf_entry_expiry", INT_PARAM, &scscf_entry_expiry},
|
|
{"db_url", PARAM_STRING, &ims_icscf_db_url},
|
|
{"db_nds_table", PARAM_STRING, &ims_icscf_db_nds_table},
|
|
{"db_scscf_table", PARAM_STRING, &ims_icscf_db_scscf_table},
|
|
{"db_capabilities_table", PARAM_STRING, &ims_icscf_db_capabilities_table},
|
|
{"cxdx_forced_peer", PARAM_STR, &cxdx_forced_peer},
|
|
{"cxdx_dest_realm", PARAM_STR, &cxdx_dest_realm},
|
|
{"preferred_scscf_uri", PARAM_STR, &preferred_scscf_uri},
|
|
{"use_preferred_scscf_uri", INT_PARAM, &use_preferred_scscf_uri},
|
|
{0, 0, 0}
|
|
};
|
|
|
|
stat_export_t mod_stats[] = {
|
|
{"uar_avg_response_time" , STAT_IS_FUNC, (stat_var**)get_avg_uar_response_time },
|
|
{"lir_avg_response_time" , STAT_IS_FUNC, (stat_var**)get_avg_lir_response_time },
|
|
{"uar_timeouts" , 0, (stat_var**)&stat_uar_timeouts },
|
|
{"lir_timeouts" , 0, (stat_var**)&stat_lir_timeouts },
|
|
{0,0,0}
|
|
};
|
|
|
|
/** module exports */
|
|
struct module_exports exports = {
|
|
"ims_icscf",
|
|
DEFAULT_DLFLAGS, /* dlopen flags */
|
|
cmds, /* Exported functions */
|
|
params,
|
|
mod_stats, /* exported statistics */
|
|
0, /* exported MI functions */
|
|
0, /* exported pseudo-variables */
|
|
0, /* extra processes */
|
|
mod_init, /* module initialization function */
|
|
0,
|
|
0,
|
|
0 /* per-child init function */
|
|
};
|
|
|
|
/**
|
|
* init module function
|
|
*/
|
|
static int mod_init(void) {
|
|
cdp_avp = 0;
|
|
int route_no;
|
|
|
|
#ifdef STATISTICS
|
|
if (register_module_stats( exports.name, mod_stats) != 0) {
|
|
LM_ERR("failed to register core statistics\n");
|
|
goto error;
|
|
}
|
|
if (!register_stats()){
|
|
LM_ERR("Unable to register statistics\n");
|
|
goto error;
|
|
}
|
|
#endif
|
|
|
|
/* initialising hash table*/
|
|
if (!i_hash_table_init(ims_icscf_hash_size)) {
|
|
LM_ERR("Error initializing the Hash Table for stored S-CSCF lists\n");
|
|
goto error;
|
|
}
|
|
|
|
/* load the TM API */
|
|
if (load_tm_api(&tmb) != 0) {
|
|
LM_ERR("can't load TM API\n");
|
|
goto error;
|
|
}
|
|
|
|
/* load the CDP API */
|
|
if (load_cdp_api(&cdpb) != 0) {
|
|
LM_ERR("can't load CDP API\n");
|
|
goto error;
|
|
}
|
|
|
|
cdp_avp = load_cdp_avp();
|
|
if (!cdp_avp) {
|
|
LM_ERR("can't load CDP_AVP API\n");
|
|
goto error;
|
|
}
|
|
|
|
/* cache the trusted domain names and capabilities */
|
|
/* bind to the db module */
|
|
if (ims_icscf_db_bind(ims_icscf_db_url) < 0)
|
|
goto error;
|
|
|
|
/* bind the SL API */
|
|
if (sl_load_api(&slb) != 0) {
|
|
LM_ERR("cannot bind to SL API\n");
|
|
return -1;
|
|
}
|
|
|
|
ims_icscf_db_init(ims_icscf_db_url, ims_icscf_db_nds_table, ims_icscf_db_scscf_table,
|
|
ims_icscf_db_capabilities_table);
|
|
|
|
I_NDS_get_trusted_domains();
|
|
I_get_capabilities();
|
|
|
|
ims_icscf_db_close();
|
|
|
|
if (!i_hash_table_init(ims_icscf_hash_size)) {
|
|
LOG(
|
|
L_ERR,
|
|
"ERR"M_NAME":mod_init: Error initializing the Hash Table for stored S-CSCF lists\n");
|
|
goto error;
|
|
}
|
|
|
|
/* register global timer used to get rid of stale scscf_lists*/
|
|
if (register_timer(ims_icscf_timer_routine, 0, 60) < 0) {
|
|
LM_ERR("failed to register timer \n");
|
|
return -1;
|
|
}
|
|
|
|
/* try to fix the xmlrpc route */
|
|
if (route_lir_user_unknown){
|
|
route_no=route_get(&main_rt, route_lir_user_unknown);
|
|
if (route_no==-1){
|
|
ERR("ims_icscf: failed to fix route \"%s\": route_get() failed\n",
|
|
route_lir_user_unknown);
|
|
return -1;
|
|
}
|
|
if (main_rt.rlist[route_no]==0){
|
|
WARN("ims_icscf: ims_icscf route \"%s\" is empty / doesn't exist\n",
|
|
route_lir_user_unknown);
|
|
}
|
|
route_lir_user_unknown_no=route_no;
|
|
}
|
|
/* try to fix the xmlrpc route */
|
|
if (route_uar_user_unknown){
|
|
route_no=route_get(&main_rt, route_uar_user_unknown);
|
|
if (route_no==-1){
|
|
ERR("ims_icscf: failed to fix route \"%s\": route_get() failed\n",
|
|
route_uar_user_unknown);
|
|
return -1;
|
|
}
|
|
if (main_rt.rlist[route_no]==0){
|
|
WARN("ims_icscf: ims_icscf route \"%s\" is empty / doesn't exist\n",
|
|
route_uar_user_unknown);
|
|
}
|
|
route_uar_user_unknown_no=route_no;
|
|
}
|
|
|
|
LM_DBG("ims_icscf module successfully initialised\n");
|
|
|
|
return 0;
|
|
error:
|
|
LM_ERR("Failed to initialise ims_icscf module\n");
|
|
return -1;
|
|
}
|
|
|
|
static int fixup_uar(void** param, int param_no)
|
|
{
|
|
if (strlen((char*) *param) <= 0) {
|
|
LM_ERR("empty parameter %d not allowed\n", param_no);
|
|
return -1;
|
|
}
|
|
|
|
if (param_no == 1) { //route name - static or dynamic string (config vars)
|
|
if (fixup_spve_null(param, param_no) < 0){
|
|
LM_ERR("fixup spve failed on %d\n", param_no);
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
return 0;
|
|
|
|
}
|
|
|
|
static int fixup_lir(void** param, int param_no)
|
|
{
|
|
if (strlen((char*) *param) <= 0) {
|
|
LM_ERR("empty parameter %d not allowed\n", param_no);
|
|
return -1;
|
|
}
|
|
|
|
if (param_no == 1) { //route name - static or dynamic string (config vars)
|
|
if (fixup_spve_null(param, param_no) < 0)
|
|
return -1;
|
|
return 0;
|
|
}
|
|
return 0;
|
|
|
|
}
|
|
|