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.
382 lines
10 KiB
382 lines
10 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*
|
|
*/
|
|
|
|
/**
|
|
* \file
|
|
*
|
|
* Interrogating-CSCF - Database operations
|
|
*
|
|
*
|
|
* \author Dragos Vingarzan vingarzan -at- fokus dot fraunhofer dot de
|
|
*
|
|
*/
|
|
|
|
#include "db.h"
|
|
|
|
#include "../../lib/srdb1/db.h"
|
|
#include "../../mem/shm_mem.h"
|
|
|
|
#include "mod.h"
|
|
|
|
static db_func_t dbf; /**< db function bindings*/
|
|
extern char * ims_icscf_db_url; /**< DB URL */
|
|
extern char * ims_icscf_db_nds_table; /**< NDS table in DB */
|
|
extern char * ims_icscf_db_scscf_table; /**< S-CSCF table in db */
|
|
extern char * ims_icscf_db_capabilities_table; /**< S-CSCF capabilities table in db */
|
|
|
|
static db1_con_t *hdl_db=0; /**< handle for the database queries */
|
|
|
|
|
|
/**
|
|
* Bind to the database module.
|
|
* @param db_url - URL of the database
|
|
* @returns 0 on success, -1 on error
|
|
*/
|
|
int ims_icscf_db_bind(char* db_url)
|
|
{
|
|
|
|
str db_url_str={db_url,strlen(db_url)};
|
|
|
|
if (db_bind_mod(&db_url_str, &dbf) < 0) {
|
|
LM_ERR("ims_icscf_db_bind: cannot bind to database module! "
|
|
"Did you forget to load a database module ?\n");
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
/**
|
|
* Init the database connection
|
|
* @param db_url - URL of the database
|
|
* @param db_table_nds - name of the NDS table
|
|
* @param db_table_scscf - name of the S-CSCF table
|
|
* @param db_table_capabilities - name of the S-CSCF capabilities table
|
|
* @returns 0 on success, -1 on error
|
|
*/
|
|
int ims_icscf_db_init(char* db_url,
|
|
char* db_table_nds,
|
|
char* db_table_scscf,
|
|
char* db_table_capabilities)
|
|
{
|
|
str db_url_str={db_url,strlen(db_url)};
|
|
|
|
if (dbf.init==0){
|
|
LM_ERR("BUG:cscf_db_init: unbound database module\n");
|
|
return -1;
|
|
}
|
|
|
|
hdl_db=dbf.init(&db_url_str);
|
|
|
|
if (hdl_db==0){
|
|
LM_ERR("ERR:ims_icscf_db_init: cannot initialize database connection\n");
|
|
goto error;
|
|
}
|
|
|
|
return 0;
|
|
|
|
error:
|
|
if (hdl_db){
|
|
dbf.close(hdl_db);
|
|
hdl_db=0;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
* Close the database connection.
|
|
*/
|
|
void ims_icscf_db_close()
|
|
{
|
|
if (!dbf.close) return;
|
|
if (hdl_db){
|
|
dbf.close(hdl_db);
|
|
hdl_db=0;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Simply check if the database connection was initialized and connect if not.
|
|
* @param db_hdl - database handle to test
|
|
* @returns 1 if connected, 0 if not
|
|
*/
|
|
static inline int ims_icscf_db_check_init(db1_con_t *db_hdl)
|
|
{
|
|
if (db_hdl) return 1;
|
|
return (ims_icscf_db_init( ims_icscf_db_url,
|
|
ims_icscf_db_nds_table,
|
|
ims_icscf_db_scscf_table,
|
|
ims_icscf_db_capabilities_table)==0);
|
|
}
|
|
|
|
|
|
static str s_trusted_domain={"trusted_domain",14};
|
|
/**
|
|
* Get the NDS list from the database.
|
|
* @param d - array of string to fill with the db contents
|
|
* @returns 1 on success, 0 on error
|
|
*/
|
|
int ims_icscf_db_get_nds(str *d[])
|
|
{
|
|
db_key_t keys_ret[] = {&s_trusted_domain};
|
|
db1_res_t * res = 0 ;
|
|
str db_table_nds_str={ims_icscf_db_nds_table,strlen(ims_icscf_db_nds_table)};
|
|
|
|
str s;
|
|
int i;
|
|
|
|
if (!ims_icscf_db_check_init(hdl_db))
|
|
goto error;
|
|
|
|
LM_DBG("DBG:ims_icscf_db_get_nds: fetching list of NDS for I-CSCF \n");
|
|
|
|
if (dbf.use_table(hdl_db, &db_table_nds_str)<0) {
|
|
LM_ERR("ERR:ims_icscf_db_init: cannot select table \"%s\"\n",db_table_nds_str.s);
|
|
goto error;
|
|
}
|
|
|
|
if (dbf.query(hdl_db, 0, 0, 0, keys_ret, 0, 1, NULL, & res) < 0) {
|
|
LM_ERR("ERR:ims_icscf_db_get_nds: db_query failed\n");
|
|
goto error;
|
|
}
|
|
|
|
if (res->n == 0) {
|
|
LM_DBG("DBG:ims_icscf_db_get_nds: I-CSCF has no NDS trusted domains in db\n");
|
|
*d=shm_malloc(sizeof(str));
|
|
if (*d==NULL){
|
|
LM_ERR("ERR:ims_icscf_db_get_nds: failed shm_malloc for 0 domains\n");
|
|
goto error;
|
|
}
|
|
(*d)[0].s=0;
|
|
(*d)[0].len=0;
|
|
}
|
|
else {
|
|
*d=shm_malloc(sizeof(str)*(res->n+1));
|
|
if (*d==NULL){
|
|
LM_ERR("ERR:ims_icscf_db_get_nds: failed shm_malloc for %d domains\n",
|
|
res->n);
|
|
goto error;
|
|
}
|
|
for(i=0;i<res->n;i++){
|
|
s.s = (char*) res->rows[i].values[0].val.string_val;
|
|
s.len = strlen(s.s);
|
|
(*d)[i].s = shm_malloc(s.len);
|
|
if ((*d)[i].s==NULL) {
|
|
LM_ERR("ERR:ims_icscf_db_get_nds: failed shm_malloc for %d bytes\n",
|
|
s.len);
|
|
(*d)[i].len = 0;
|
|
}else{
|
|
(*d)[i].len = s.len;
|
|
memcpy((*d)[i].s,s.s,s.len);
|
|
}
|
|
}
|
|
(*d)[res->n].s=0;
|
|
(*d)[res->n].len=0;
|
|
}
|
|
|
|
LM_DBG("INF:ims_icscf_db_get_nds: Loaded %d trusted domains\n",
|
|
res->n);
|
|
|
|
dbf.free_result( hdl_db, res);
|
|
return 1;
|
|
error:
|
|
if (res)
|
|
dbf.free_result( hdl_db, res);
|
|
*d=shm_malloc(sizeof(str));
|
|
if (*d==NULL)
|
|
LM_ERR("ERR:ims_icscf_db_get_nds: failed shm_malloc for 0 domains\n");
|
|
else {
|
|
(*d)[0].s=0;
|
|
(*d)[0].len=0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
static str s_id={"id",2};
|
|
static str s_s_cscf_uri={"s_cscf_uri",10};
|
|
/**
|
|
* Get the S-CSCF names from the database and create the S-CSCF set.
|
|
* @param cap - array of scscf_capabilities to fill with the db contents for the S-CSCF names
|
|
* @returns 1 on success, 0 on error
|
|
*/
|
|
int ims_icscf_db_get_scscf(scscf_capabilities *cap[])
|
|
{
|
|
|
|
db_key_t keys_ret[] = {&s_id,&s_s_cscf_uri};
|
|
db_key_t key_ord = &s_id;
|
|
db1_res_t * res = 0 ;
|
|
str db_table_scscf_str={ims_icscf_db_scscf_table,strlen(ims_icscf_db_scscf_table)};
|
|
|
|
int i;
|
|
|
|
*cap = 0;
|
|
|
|
if (!ims_icscf_db_check_init(hdl_db))
|
|
goto error;
|
|
|
|
LM_DBG("DBG:ims_icscf_db_get_scscf: fetching S-CSCFs \n");
|
|
|
|
if (dbf.use_table(hdl_db, &db_table_scscf_str)<0) {
|
|
LM_ERR("ERR:ims_icscf_db_init: cannot select table \"%s\"\n",db_table_scscf_str.s);
|
|
goto error;
|
|
}
|
|
|
|
if (dbf.query(hdl_db, 0, 0, 0, keys_ret, 0, 2, key_ord, & res) < 0) {
|
|
LM_ERR("ERR:ims_icscf_db_get_scscf: db_query failed\n");
|
|
goto error;
|
|
}
|
|
|
|
if (res->n == 0) {
|
|
LM_ERR("ERR:ims_icscf_db_get_scscf: no S-CSCFs found\n");
|
|
goto error;
|
|
}
|
|
else {
|
|
*cap = shm_malloc(sizeof(scscf_capabilities)*res->n);
|
|
if (!(*cap)) {
|
|
LM_ERR("ERR:ims_icscf_db_get_scscf: Error allocating %lx bytes\n",
|
|
sizeof(scscf_capabilities)*res->n);
|
|
goto error;
|
|
}
|
|
memset((*cap),0,sizeof(scscf_capabilities)*res->n);
|
|
for(i=0;i<res->n;i++){
|
|
(*cap)[i].id_s_cscf = res->rows[i].values[0].val.int_val;
|
|
(*cap)[i].scscf_name.len = strlen(res->rows[i].values[1].val.string_val);
|
|
(*cap)[i].scscf_name.s = shm_malloc((*cap)[i].scscf_name.len);
|
|
if (!(*cap)[i].scscf_name.s){
|
|
LM_ERR("ERR:ims_icscf_db_get_scscf: Error allocating %d bytes\n",
|
|
(*cap)[i].scscf_name.len);
|
|
(*cap)[i].scscf_name.len=0;
|
|
goto error;
|
|
}
|
|
memcpy((*cap)[i].scscf_name.s,res->rows[i].values[1].val.string_val,
|
|
(*cap)[i].scscf_name.len);
|
|
}
|
|
}
|
|
|
|
dbf.free_result( hdl_db, res);
|
|
|
|
// return the size of scscf set
|
|
return i;
|
|
|
|
error:
|
|
if (res)
|
|
dbf.free_result( hdl_db, res);
|
|
return 0;
|
|
}
|
|
|
|
static str s_id_s_cscf={"id_s_cscf",9};
|
|
static str s_capability={"capability",10};
|
|
/**
|
|
* Get the S-CSCF capabilities from the database and fill the S-CSCF set.
|
|
* @param cap - array of scscf_capabilities to fill with capabilities
|
|
* @returns 1 on success, 0 on error
|
|
*/
|
|
int ims_icscf_db_get_capabilities(scscf_capabilities *cap[],int cap_cnt)
|
|
{
|
|
db_key_t keys_ret[] = {&s_id_s_cscf,&s_capability};
|
|
db_key_t key_ord = &s_id_s_cscf;
|
|
db1_res_t * res = 0 ;
|
|
str db_table_capabilities_str={ims_icscf_db_capabilities_table,strlen(ims_icscf_db_capabilities_table)};
|
|
|
|
|
|
int i,j;
|
|
int ccnt=0;
|
|
int cnt;
|
|
|
|
|
|
if (!ims_icscf_db_check_init(hdl_db))
|
|
goto error;
|
|
|
|
LM_DBG("DBG:ims_icscf_db_get_capabilities: fetching list of Capabilities for I-CSCF\n");
|
|
|
|
if (dbf.use_table(hdl_db, &db_table_capabilities_str)<0) {
|
|
LM_ERR("ERR:ims_icscf_db_init: cannot select table \"%s\"\n",db_table_capabilities_str.s);
|
|
goto error;
|
|
}
|
|
|
|
if (dbf.query(hdl_db, 0, 0, 0, keys_ret, 0, 2, key_ord, & res) < 0) {
|
|
LM_ERR("ERR:ims_icscf_db_get_capabilities: db_query failed\n");
|
|
goto error;
|
|
}
|
|
|
|
if (res->n == 0) {
|
|
LM_DBG("DBG:ims_icscf_db_get_capabilities: No Capabilites found... not critical...\n");
|
|
return 1;
|
|
}
|
|
else {
|
|
for(i=0;i<cap_cnt;i++){
|
|
cnt = 0;
|
|
for(j=0;j<res->n;j++)
|
|
if (res->rows[j].values[0].val.int_val == (*cap)[i].id_s_cscf)
|
|
cnt++;
|
|
(*cap)[i].capabilities = shm_malloc(sizeof(int)*cnt);
|
|
if (!(*cap)[i].capabilities) {
|
|
LM_ERR("ERR:ims_icscf_db_get_capabilities: Error allocating %lx bytes\n",
|
|
sizeof(int)*cnt);
|
|
(*cap)[i].cnt=0;
|
|
goto error;
|
|
}
|
|
cnt=0;
|
|
for(j=0;j<res->n;j++)
|
|
if (res->rows[j].values[0].val.int_val == (*cap)[i].id_s_cscf) {
|
|
(*cap)[i].capabilities[cnt++]=res->rows[j].values[1].val.int_val;
|
|
ccnt++;
|
|
}
|
|
(*cap)[i].cnt=cnt;
|
|
}
|
|
|
|
}
|
|
LM_DBG("INF:ims_icscf_db_get_capabilities: Loaded %d capabilities for %d S-CSCFs (%d invalid entries in db)\n",
|
|
ccnt,cap_cnt,res->n-ccnt);
|
|
dbf.free_result( hdl_db, res);
|
|
return 1;
|
|
|
|
error:
|
|
if (res)
|
|
dbf.free_result( hdl_db, res);
|
|
return 0;
|
|
}
|