diff --git a/src/modules/carrierroute/cr_db.c b/src/modules/carrierroute/cr_db.c index d651db1b49c..010f99d7158 100644 --- a/src/modules/carrierroute/cr_db.c +++ b/src/modules/carrierroute/cr_db.c @@ -265,6 +265,7 @@ int load_user_carrier(str * user, str * domain) { */ int load_route_data_db(struct route_data_t * rd) { db1_res_t * res = NULL; + db1_res_t * prob_res = NULL; db_row_t * row = NULL; int i, ret; struct carrier_data_t * tmp_carrier_data; @@ -352,6 +353,7 @@ int load_route_data_db(struct route_data_t * rd) { } } int n = 0; + boolean query_done = false; do { LM_DBG("loading, cycle %d", n++); for (i = 0; i < RES_ROW_N(res); ++i) { @@ -396,6 +398,35 @@ int load_route_data_db(struct route_data_t * rd) { p_tmp_comment) == -1) { goto errout; } + if (row->values[COL_PROB].val.double_val == 0 && !query_done) { + int ret_tmp; + char query_tmp[QUERY_LEN]; + str query_tmp_str; + + memset(query_tmp, 0, QUERY_LEN); + ret_tmp = snprintf(query_tmp, QUERY_LEN, "SELECT * FROM %.*s WHERE %.*s=%d and %.*s=%d and %.*s>%d", + carrierroute_table.len, carrierroute_table.s, columns[COL_CARRIER]->len, columns[COL_CARRIER]->s, row->values[COL_CARRIER].val.int_val, + columns[COL_DOMAIN]->len, columns[COL_DOMAIN]->s, row->values[COL_DOMAIN].val.int_val, columns[COL_PROB]->len, columns[COL_PROB]->s, 0); + + if (ret_tmp < 0) { + LM_ERR("error in snprintf while querying prob column"); + goto errout; + } + query_tmp_str.s = query_tmp; + query_tmp_str.len = ret_tmp; + + if (carrierroute_dbf.raw_query(carrierroute_dbh, &query_tmp_str, &prob_res) < 0) { + LM_ERR("Failed to query carrierroute db table based on prob column.\n"); + goto errout; + } + if(RES_ROW_N(prob_res) == 0) { + LM_ERR("Carrierroute db table contains route(s) with only 0 probability.\n"); + query_done = true; + } + carrierroute_dbf.free_result(carrierroute_dbh, prob_res); + prob_res = NULL; + } + } if (DB_CAPABILITY(carrierroute_dbf, DB_CAP_FETCH)) { if(carrierroute_dbf.fetch_result(carrierroute_dbh, &res, cfg_get(carrierroute, carrierroute_cfg, fetch_rows)) < 0) { @@ -462,5 +493,8 @@ int load_route_data_db(struct route_data_t * rd) { if (res) { carrierroute_dbf.free_result(carrierroute_dbh, res); } + if (prob_res) { + carrierroute_dbf.free_result(carrierroute_dbh, prob_res); + } return -1; } diff --git a/src/modules/carrierroute/cr_db.h b/src/modules/carrierroute/cr_db.h index 1f53c9307bd..ffea7311928 100644 --- a/src/modules/carrierroute/cr_db.h +++ b/src/modules/carrierroute/cr_db.h @@ -88,4 +88,9 @@ int load_route_data_db (struct route_data_t * rd); int load_user_carrier(str * user, str * domain); +typedef enum { + false = 0, + true = 1 +} boolean; + #endif diff --git a/src/modules/carrierroute/cr_func.c b/src/modules/carrierroute/cr_func.c index 6b6db1387bb..c4ce4d52a00 100644 --- a/src/modules/carrierroute/cr_func.c +++ b/src/modules/carrierroute/cr_func.c @@ -471,7 +471,7 @@ static int rewrite_on_rule(struct route_flags *rf_head, flag_t flags, str * dest avp_value_t cr_new_uri; if(rf->dice_max == 0) { - LM_ERR("invalid dice_max value\n"); + LM_ERR("invalid dice_max value (route has probability 0)\n"); return -1; } if ((prob = hash_func(msg, hash_source, rf->dice_max)) < 0) { diff --git a/src/modules/dialog/README b/src/modules/dialog/README index f344c99b532..f56c64cad80 100644 --- a/src/modules/dialog/README +++ b/src/modules/dialog/README @@ -1979,15 +1979,17 @@ kamcmd dlg.list _from_ _to_ _op_ 11.1. event_route[dialog:start] - Executed when 200OK for INVITE is processed. + Executed when 200OK reply for INVITE is processed. 11.2. event_route[dialog:end] - Executed when BYE is processed or dialog timed out. + Executed when the BYE for the call is processed or the dialog timed + out. 11.3. event_route[dialog:failed] - Executed when dialog is not completed (+300 reply to INVITE). + Executed when dialog is not completed (300 or greater reply code to + INVITE). Chapter 2. Developer Guide diff --git a/src/modules/dialog/doc/dialog_admin.xml b/src/modules/dialog/doc/dialog_admin.xml index e451ce4b9d9..4823de489d1 100644 --- a/src/modules/dialog/doc/dialog_admin.xml +++ b/src/modules/dialog/doc/dialog_admin.xml @@ -2344,7 +2344,7 @@ if(has_totag() and is_present_hf("Route") and uri==myself ) {
- <varname>dlg.end_dlg</varname> + dlg.end_dlg Terminates an ongoing dialog by sending BYE in both directions. @@ -2544,21 +2544,23 @@ if(has_totag() and is_present_hf("Route") and uri==myself ) {
Event Routes
- <varname>event_route[dialog:start]</varname> + event_route[dialog:start] - Executed when 200OK for INVITE is processed. + Executed when 200OK reply for INVITE is processed.
- <varname>event_route[dialog:end]</varname> + event_route[dialog:end] - Executed when BYE is processed or dialog timed out. + Executed when the BYE for the call is processed + or the dialog timed out.
- <varname>event_route[dialog:failed]</varname> + event_route[dialog:failed] - Executed when dialog is not completed (+300 reply to INVITE). + Executed when dialog is not completed (300 or greater reply code + to INVITE).
diff --git a/src/modules/seas/cluster.h b/src/modules/seas/cluster.h index 6c18116d6c2..b3e596736f1 100644 --- a/src/modules/seas/cluster.h +++ b/src/modules/seas/cluster.h @@ -1,5 +1,4 @@ -/* $Id$ - * +/* * Copyright (C) 2006-2007 VozTelecom Sistemas S.L * * This file is part of Kamailio, a free SIP server. @@ -14,8 +13,8 @@ * 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 + * 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 */ diff --git a/src/modules/seas/encode_allow.h b/src/modules/seas/encode_allow.h index e48ace7a7df..b4663e13f5d 100644 --- a/src/modules/seas/encode_allow.h +++ b/src/modules/seas/encode_allow.h @@ -1,5 +1,4 @@ -/* $Id$ - * +/* * Copyright (C) 2006-2007 VozTelecom Sistemas S.L * * This file is part of Kamailio, a free SIP server. @@ -14,11 +13,14 @@ * 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 + * 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 */ +#ifndef __ENCODE_ALLOW_H__ +#define __ENCODE_ALLOW_H__ int encode_allow(char *hdrstart,int hdrlen,unsigned int *bodi,char *where); int print_encoded_allow(FILE *fd,char *hdr,int hdrlen,unsigned char* payload,int paylen,char *prefix); +#endif diff --git a/src/modules/seas/encode_content_disposition.h b/src/modules/seas/encode_content_disposition.h index 63d81de366d..48045289f6c 100644 --- a/src/modules/seas/encode_content_disposition.h +++ b/src/modules/seas/encode_content_disposition.h @@ -1,5 +1,4 @@ -/* $Id$ - * +/* * Copyright (C) 2006-2007 VozTelecom Sistemas S.L * * This file is part of Kamailio, a free SIP server. @@ -14,11 +13,14 @@ * 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 + * 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 */ +#ifndef __ENCODE_CONTENT_DISPOSITION_H__ +#define __ENCODE_CONTENT_DISPOSITION_H__ int encode_content_disposition(char *hdrstart,int hdrlen,struct disposition *body,unsigned char *where); int print_encoded_content_disposition(FILE *fd,char *hdr,int hdrlen,unsigned char* payload,int paylen,char *prefix); +#endif diff --git a/src/modules/seas/encode_content_length.h b/src/modules/seas/encode_content_length.h index fc58dbcf9ce..deb1cc40467 100644 --- a/src/modules/seas/encode_content_length.h +++ b/src/modules/seas/encode_content_length.h @@ -1,5 +1,4 @@ -/* $Id$ - * +/* * Copyright (C) 2006-2007 VozTelecom Sistemas S.L * * This file is part of Kamailio, a free SIP server. @@ -14,11 +13,13 @@ * 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 + * 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 */ - +#ifndef __ENCODE_CONTENT_LENGHT_H__ +#define __ENCODE_CONTENT_LENGHT_H__ int encode_contentlength(char *hdr,int hdrlen,long int len,char *where); int print_encoded_contentlength(FILE* fd,char *hdr,int hdrlen,unsigned char *payload,int paylen,char *prefix); +#endif diff --git a/src/modules/seas/encode_content_type.h b/src/modules/seas/encode_content_type.h index e52d81d3b4f..b3d359c86a6 100644 --- a/src/modules/seas/encode_content_type.h +++ b/src/modules/seas/encode_content_type.h @@ -1,5 +1,4 @@ -/* $Id$ - * +/* * Copyright (C) 2006-2007 VozTelecom Sistemas S.L * * This file is part of Kamailio, a free SIP server. @@ -14,15 +13,17 @@ * 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 + * 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 */ - +#ifndef __ENCODE_CONTENT_TYPE_H__ +#define __ENCODE_CONTENT_TYPE_H__ int encode_content_type(char *hdrstart,int hdrlen,unsigned int bodi,char *where); int encode_accept(char *hdrstart,int hdrlen,unsigned int *bodi,char *where); int encode_mime_type(char *hdrstart,int hdrlen,unsigned int bodi,char *where); int print_encoded_mime_type(FILE* fd,char *hdr,int hdrlen,unsigned int* payload,int paylen,char *prefix); int print_encoded_content_type(FILE* fd,char *hdr,int hdrlen,unsigned char* payload,int paylen,char *prefix); int print_encoded_accept(FILE* fd,char *hdr,int hdrlen,unsigned char* payload,int paylen,char *prefix); +#endif diff --git a/src/modules/seas/encode_cseq.h b/src/modules/seas/encode_cseq.h index 54aaed1022a..bcba4b864c9 100644 --- a/src/modules/seas/encode_cseq.h +++ b/src/modules/seas/encode_cseq.h @@ -1,5 +1,4 @@ -/* $Id$ - * +/* * Copyright (C) 2006-2007 VozTelecom Sistemas S.L * * This file is part of Kamailio, a free SIP server. @@ -14,13 +13,15 @@ * 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 + * 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 */ - +#ifndef __ENCODE_CSEQ_H__ +#define __ENCODE_CSEQ_H__ #include "../../core/str.h" #include "../../core/parser/msg_parser.h" int encode_cseq(char *hdrstart,int hdrlen,struct cseq_body *body,unsigned char *where); int print_encoded_cseq(FILE* fd,char *hdr,int hdrlen,unsigned char* payload,int paylen,char *prefix); +#endif diff --git a/src/modules/seas/encode_digest.h b/src/modules/seas/encode_digest.h index e91ff12180d..26952c22822 100644 --- a/src/modules/seas/encode_digest.h +++ b/src/modules/seas/encode_digest.h @@ -1,5 +1,4 @@ -/* $Id$ - * +/* * Copyright (C) 2006-2007 VozTelecom Sistemas S.L * * This file is part of Kamailio, a free SIP server. @@ -14,12 +13,14 @@ * 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 + * 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 */ - +#ifndef __ENCODE_DIGEST_H__ +#define __ENCODE_DIGEST_H__ int encode_digest(char *hdrstart,int hdrlen,dig_cred_t *digest,unsigned char *where); int print_encoded_digest(FILE* fd,char *hdr,int hdrlen,unsigned char* payload,int paylen,char *prefix); int dump_digest_test(char *hdr,int hdrlen,unsigned char* payload,int paylen,FILE* fd,char segregationLevel); +#endif diff --git a/src/modules/seas/seas.c b/src/modules/seas/seas.c index 0c162db5df7..c6c99a9b8b9 100644 --- a/src/modules/seas/seas.c +++ b/src/modules/seas/seas.c @@ -1,5 +1,4 @@ -/* $Id$ - * +/* * Copyright (C) 2006-2007 VozTelecom Sistemas S.L * * This file is part of Kamailio, a free SIP server. @@ -14,8 +13,8 @@ * 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 + * 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 */ @@ -89,20 +88,20 @@ struct seas_functions seas_f; static cmd_export_t cmds[]= { {"as_relay_t", (cmd_function)w_as_relay_t, 1, fixup_as_relay, - 0, REQUEST_ROUTE}, + 0, REQUEST_ROUTE}, {"as_relay_sl", (cmd_function)w_as_relay_sl, 1, fixup_as_relay, - 0, REQUEST_ROUTE}, + 0, REQUEST_ROUTE}, {0,0,0,0,0,0} }; static param_export_t params[]= { - {"listen_sockets",PARAM_STRING, &seas_listen_socket}, - {"stats_socket", PARAM_STRING, &seas_stats_socket}, - {"jain_ping", PARAM_STRING, &jain_ping_config}, - {"servlet_ping", PARAM_STRING, &servlet_ping_config}, - {"clusters", PARAM_STRING, &cluster_cfg}, - {0,0,0} + {"listen_sockets",PARAM_STRING, &seas_listen_socket}, + {"stats_socket", PARAM_STRING, &seas_stats_socket}, + {"jain_ping", PARAM_STRING, &jain_ping_config}, + {"servlet_ping", PARAM_STRING, &servlet_ping_config}, + {"clusters", PARAM_STRING, &cluster_cfg}, + {0,0,0} }; static proc_export_t seas_procs[] = { @@ -110,65 +109,65 @@ static proc_export_t seas_procs[] = { {0,0,0,0,0} }; -struct module_exports exports= +struct module_exports exports= { - "seas", - DEFAULT_DLFLAGS, - cmds, /* exported commands */ - params, /* exported parameters */ - 0, /* exported statistics */ - 0, /* exported mi commands */ - 0, /* exported module-items (pseudo variables) */ - seas_procs, /* extra processes */ - seas_init, /* module initialization function */ - 0, /* response function */ - (destroy_function) seas_exit, /* module exit function */ - (child_init_function) seas_child_init /* per-child init function */ + "seas", + DEFAULT_DLFLAGS, + cmds, /* exported commands */ + params, /* exported parameters */ + 0, /* exported statistics */ + 0, /* exported mi commands */ + 0, /* exported module-items (pseudo variables) */ + seas_procs, /* extra processes */ + seas_init, /* module initialization function */ + 0, /* response function */ + (destroy_function) seas_exit, /* module exit function */ + (child_init_function) seas_child_init /* per-child init function */ }; static int fixup_as_relay(void** param, int param_no) { - int len; - char *parameter; - struct as_entry **entry,*tmp; - - parameter=(char *)(*param); - - if (param_no!=1) - return 0; - len=strlen(parameter); - - for (entry=&as_list;*entry;entry=&((*entry)->next)) { - if (len== (*entry)->name.len && - !memcmp((*entry)->name.s,parameter,len)) { - pkg_free(*param); - *param=*entry; - return 1; - } - } - if (!(*entry)) { - if (!(*entry=(struct as_entry *)shm_malloc(sizeof(struct as_entry)))) { - LM_ERR("no more shm_mem\n"); - goto error; - } - memset(*entry,0,sizeof(struct as_entry)); - if(!((*entry)->name.s=shm_malloc(len))){ - LM_ERR("no more share mem\n"); - goto error; - } - (*entry)->name.len=len; - memcpy((*entry)->name.s,parameter,len); - (*entry)->u.as.name=(*entry)->name; - (*entry)->u.as.event_fd=(*entry)->u.as.action_fd=-1; - (*entry)->type=AS_TYPE; - pkg_free(*param); - *param=*entry; - } - for (tmp=as_list;tmp;tmp=tmp->next) - LM_DBG("%.*s\n",tmp->name.len,tmp->name.s); - return 1; + int len; + char *parameter; + struct as_entry **entry,*tmp; + + parameter=(char *)(*param); + + if (param_no!=1) + return 0; + len=strlen(parameter); + + for (entry=&as_list;*entry;entry=&((*entry)->next)) { + if (len== (*entry)->name.len && + !memcmp((*entry)->name.s,parameter,len)) { + pkg_free(*param); + *param=*entry; + return 1; + } + } + if (!(*entry)) { + if (!(*entry=(struct as_entry *)shm_malloc(sizeof(struct as_entry)))) { + LM_ERR("no more shm_mem\n"); + goto error; + } + memset(*entry,0,sizeof(struct as_entry)); + if(!((*entry)->name.s=shm_malloc(len))){ + LM_ERR("no more share mem\n"); + goto error; + } + (*entry)->name.len=len; + memcpy((*entry)->name.s,parameter,len); + (*entry)->u.as.name=(*entry)->name; + (*entry)->u.as.event_fd=(*entry)->u.as.action_fd=-1; + (*entry)->type=AS_TYPE; + pkg_free(*param); + *param=*entry; + } + for (tmp=as_list;tmp;tmp=tmp->next) + LM_DBG("%.*s\n",tmp->name.len,tmp->name.s); + return 1; error: - return -1; + return -1; } /** @@ -176,57 +175,57 @@ static int fixup_as_relay(void** param, int param_no) */ void seas_sighandler(int signo) { - struct as_entry *as; - if(is_dispatcher) - sig_flag=signo; - switch(signo){ - case SIGPIPE: - if(is_dispatcher) - return; - LM_INFO("%s exiting\n",whoami); - if(my_as->u.as.ac_buffer.s){ - pkg_free(my_as->u.as.ac_buffer.s); - my_as->u.as.ac_buffer.s=0; - } - if(my_as->u.as.action_fd!=-1){ - close(my_as->u.as.action_fd); - my_as->u.as.action_fd=-1; - } - exit(0); - break; - case SIGCHLD: - LM_INFO("Child stopped or terminated\n"); - break; - case SIGUSR1: - case SIGUSR2: - LM_DBG("Memory status (pkg):\n"); + struct as_entry *as; + if(is_dispatcher) + sig_flag=signo; + switch(signo){ + case SIGPIPE: + if(is_dispatcher) + return; + LM_INFO("%s exiting\n",whoami); + if(my_as->u.as.ac_buffer.s){ + pkg_free(my_as->u.as.ac_buffer.s); + my_as->u.as.ac_buffer.s=0; + } + if(my_as->u.as.action_fd!=-1){ + close(my_as->u.as.action_fd); + my_as->u.as.action_fd=-1; + } + exit(0); + break; + case SIGCHLD: + LM_INFO("Child stopped or terminated\n"); + break; + case SIGUSR1: + case SIGUSR2: + LM_DBG("Memory status (pkg):\n"); #ifdef PKG_MALLOC - pkg_status(); + pkg_status(); #endif - break; - case SIGINT: - case SIGTERM: - LM_INFO("INFO: signal %d received\n",signo); + break; + case SIGINT: + case SIGTERM: + LM_INFO("INFO: signal %d received\n",signo); #ifdef PKG_MALLOC - pkg_status(); + pkg_status(); #endif - if(is_dispatcher){ - for (as=as_list;as;as=as->next) { - if(as->type==AS_TYPE && as->connected) - kill(as->u.as.action_pid,signo); - } - while(wait(0) > 0); - exit(0); - }else{ - LM_INFO("%s exiting\n",whoami); - if(my_as && my_as->u.as.ac_buffer.s) - pkg_free(my_as->u.as.ac_buffer.s); - if(my_as && my_as->u.as.action_fd!=-1) - close(my_as->u.as.action_fd); - exit(0); - } - break; - } + if(is_dispatcher){ + for (as=as_list;as;as=as->next) { + if(as->type==AS_TYPE && as->connected) + kill(as->u.as.action_pid,signo); + } + while(wait(0) > 0); + exit(0); + }else{ + LM_INFO("%s exiting\n",whoami); + if(my_as && my_as->u.as.ac_buffer.s) + pkg_free(my_as->u.as.ac_buffer.s); + if(my_as && my_as->u.as.action_fd!=-1) + close(my_as->u.as.action_fd); + exit(0); + } + break; + } } /** @@ -235,112 +234,112 @@ void seas_sighandler(int signo) */ static int w_as_relay_t(struct sip_msg *msg, char *entry, char *foo) { - as_msg_p my_as_ev; - int new_tran,ret=0,len; - char *buffer,processor_id; - struct cell *mycel; - struct as_entry *as; - char *msg100="Your call is important to us"; - char *msg500="Server Internal Error!"; - - buffer=(char*)0; - my_as_ev=(as_msg_p)0; - - /** - * returns <0 on error - * 1 if (new transaction was created) or if (ACK for locally replied 200 with totag) or if (ACK for code>=300) - * 0 if it was a retransmission - */ - new_tran = seas_f.tmb.t_newtran(msg); - if(new_tran<0) { - ret = (ser_error==E_BAD_VIA && reply_to_via) ? 0 : new_tran; - goto done; - } - /*retransmission: script processing should be stopped*/ - if (new_tran==0 && !(msg->REQ_METHOD==METHOD_ACK)){ - ret = 0; - goto done; - } - /*new transaction created, let's pass it to an APP SERVER*/ - if (msg->REQ_METHOD==METHOD_INVITE ) - { - LM_DBG("new INVITE\n"); - if(!seas_f.tmb.t_reply(msg,100,msg100)){ - LM_DBG("t_reply (100)\n"); - goto error; - } - } - as=(struct as_entry *)entry; - if(!as->connected){ - LM_ERR("app server %.*s not connected\n",as->name.len,as->name.s); - goto error; - } - if(as->type==AS_TYPE){ - if((processor_id=get_processor_id(&msg->rcv,&(as->u.as)))<0){ - LM_ERR("no processor found for packet dst %s:%d\n",ip_addr2a(&msg->rcv.dst_ip),msg->rcv.dst_port); - goto error; - } - }else if(as->type==CLUSTER_TYPE){ - LM_ERR("clustering not fully implemented\n"); - return 0; - }else{ - LM_ERR("unknown type of as (neither cluster nor as)\n"); - return -1; - } - LM_DBG("as found ! (%.*s) processor id = %d\n",as->name.len,as->name.s,processor_id); - if(new_tran==1 && msg->REQ_METHOD==METHOD_ACK){ - LM_DBG("message handled in transaction callbacks. skipping\n"); - ret = 0; - goto done; - /* core should forward statelessly (says t_newtran) - LM_DBG("forwarding statelessly !!!\n"); - if(!(buffer=create_as_event_sl(msg,processor_id,&len,0))){ - LM_ERR("create_as_event_sl() unable to create event code\n"); - goto error; - } - */ - }else if(!(buffer=create_as_event_t(seas_f.tmb.t_gett(),msg,processor_id,&len,0))){ - LM_ERR("unable to create event code\n"); - goto error; - } - if(!(my_as_ev=shm_malloc(sizeof(as_msg_t)))){ - LM_ERR("Out of shared mem!\n"); - goto error; - } - my_as_ev->msg = buffer; - my_as_ev->as = as; - my_as_ev->type = T_REQ_IN; - my_as_ev->len = len; - my_as_ev->transaction=seas_f.tmb.t_gett(); /*does not refcount*/ - if(use_stats && new_tran>0) - as_relay_stat(seas_f.tmb.t_gett()); + as_msg_p my_as_ev; + int new_tran,ret=0,len; + char *buffer,processor_id; + struct cell *mycel; + struct as_entry *as; + char *msg100="Your call is important to us"; + char *msg500="Server Internal Error!"; + + buffer=(char*)0; + my_as_ev=(as_msg_p)0; + + /** + * returns <0 on error + * 1 if (new transaction was created) or if (ACK for locally replied 200 with totag) or if (ACK for code>=300) + * 0 if it was a retransmission + */ + new_tran = seas_f.tmb.t_newtran(msg); + if(new_tran<0) { + ret = (ser_error==E_BAD_VIA && reply_to_via) ? 0 : new_tran; + goto done; + } + /*retransmission: script processing should be stopped*/ + if (new_tran==0 && !(msg->REQ_METHOD==METHOD_ACK)){ + ret = 0; + goto done; + } + /*new transaction created, let's pass it to an APP SERVER*/ + if (msg->REQ_METHOD==METHOD_INVITE ) + { + LM_DBG("new INVITE\n"); + if(!seas_f.tmb.t_reply(msg,100,msg100)){ + LM_DBG("t_reply (100)\n"); + goto error; + } + } + as=(struct as_entry *)entry; + if(!as->connected){ + LM_ERR("app server %.*s not connected\n",as->name.len,as->name.s); + goto error; + } + if(as->type==AS_TYPE){ + if((processor_id=get_processor_id(&msg->rcv,&(as->u.as)))<0){ + LM_ERR("no processor found for packet dst %s:%d\n",ip_addr2a(&msg->rcv.dst_ip),msg->rcv.dst_port); + goto error; + } + }else if(as->type==CLUSTER_TYPE){ + LM_ERR("clustering not fully implemented\n"); + return 0; + }else{ + LM_ERR("unknown type of as (neither cluster nor as)\n"); + return -1; + } + LM_DBG("as found ! (%.*s) processor id = %d\n",as->name.len,as->name.s,processor_id); + if(new_tran==1 && msg->REQ_METHOD==METHOD_ACK){ + LM_DBG("message handled in transaction callbacks. skipping\n"); + ret = 0; + goto done; + /* core should forward statelessly (says t_newtran) + * LM_DBG("forwarding statelessly !!!\n"); + * if(!(buffer=create_as_event_sl(msg,processor_id,&len,0))){ + * LM_ERR("create_as_event_sl() unable to create event code\n"); + * goto error; + * } + */ + }else if(!(buffer=create_as_event_t(seas_f.tmb.t_gett(),msg,processor_id,&len,0))){ + LM_ERR("unable to create event code\n"); + goto error; + } + if(!(my_as_ev=shm_malloc(sizeof(as_msg_t)))){ + LM_ERR("Out of shared mem!\n"); + goto error; + } + my_as_ev->msg = buffer; + my_as_ev->as = as; + my_as_ev->type = T_REQ_IN; + my_as_ev->len = len; + my_as_ev->transaction=seas_f.tmb.t_gett(); /*does not refcount*/ + if(use_stats && new_tran>0) + as_relay_stat(seas_f.tmb.t_gett()); again: - ret=write(write_pipe,&my_as_ev,sizeof(as_msg_p)); - if(ret==-1){ - if(errno==EINTR) - goto again; - else if(errno==EPIPE){ - LM_ERR("SEAS Event Dispatcher has closed the pipe. Invalidating it !\n"); - goto error; - /** TODO handle this correctly !!!*/ - } - } - /* seas_f.tmb.t_setkr(REQ_FWDED); */ - ret=0; + ret=write(write_pipe,&my_as_ev,sizeof(as_msg_p)); + if(ret==-1){ + if(errno==EINTR) + goto again; + else if(errno==EPIPE){ + LM_ERR("SEAS Event Dispatcher has closed the pipe. Invalidating it !\n"); + goto error; + /** TODO handle this correctly !!!*/ + } + } + /* seas_f.tmb.t_setkr(REQ_FWDED); */ + ret=0; done: - return ret; + return ret; error: - mycel=seas_f.tmb.t_gett(); - if(mycel && mycel!=T_UNDEFINED){ - if(!seas_f.tmb.t_reply(msg,500,msg500)){ - LM_ERR("t_reply (500)\n"); - } - } - if(my_as_ev) - shm_free(my_as_ev); - if(buffer) - shm_free(buffer); - return ret; + mycel=seas_f.tmb.t_gett(); + if(mycel && mycel!=T_UNDEFINED){ + if(!seas_f.tmb.t_reply(msg,500,msg500)){ + LM_ERR("t_reply (500)\n"); + } + } + if(my_as_ev) + shm_free(my_as_ev); + if(buffer) + shm_free(buffer); + return ret; } @@ -350,274 +349,274 @@ static int w_as_relay_t(struct sip_msg *msg, char *entry, char *foo) */ static int w_as_relay_sl(struct sip_msg *msg, char *as_name, char *foo) { - as_msg_p my_as_ev=0; - int ret=0,len; - char *buffer=0,processor_id; - struct as_entry *as; - - as=(struct as_entry *)as_name; - - if(as->type==AS_TYPE){ - if((processor_id=get_processor_id(&msg->rcv,&(as->u.as)))<0){ - LM_ERR("no processor found for packet with dst port:%d\n",msg->rcv.dst_port); - goto error; - } - }else if (as->type==CLUSTER_TYPE) { - LM_ERR("clustering not fully implemented\n"); - goto error; - }else{ - LM_ERR("unknown type of as\n"); - goto error; - } - - LM_DBG("as found ! (%.*s) processor id = %d\n",as->name.len,as->name.s,processor_id); - if(!(buffer=create_as_event_sl(msg,processor_id,&len,0))){ - LM_ERR("unable to create event code\n"); - goto error; - } - if(!(my_as_ev=shm_malloc(sizeof(as_msg_t)))) - goto error; - my_as_ev->msg = buffer; - my_as_ev->as = as; - my_as_ev->type = SL_REQ_IN; - my_as_ev->len = len; - my_as_ev->transaction=seas_f.tmb.t_gett(); /*does not refcount*/ - if(use_stats) - as_relay_stat(seas_f.tmb.t_gett()); + as_msg_p my_as_ev=0; + int ret=0,len; + char *buffer=0,processor_id; + struct as_entry *as; + + as=(struct as_entry *)as_name; + + if(as->type==AS_TYPE){ + if((processor_id=get_processor_id(&msg->rcv,&(as->u.as)))<0){ + LM_ERR("no processor found for packet with dst port:%d\n",msg->rcv.dst_port); + goto error; + } + }else if (as->type==CLUSTER_TYPE) { + LM_ERR("clustering not fully implemented\n"); + goto error; + }else{ + LM_ERR("unknown type of as\n"); + goto error; + } + + LM_DBG("as found ! (%.*s) processor id = %d\n",as->name.len,as->name.s,processor_id); + if(!(buffer=create_as_event_sl(msg,processor_id,&len,0))){ + LM_ERR("unable to create event code\n"); + goto error; + } + if(!(my_as_ev=shm_malloc(sizeof(as_msg_t)))) + goto error; + my_as_ev->msg = buffer; + my_as_ev->as = as; + my_as_ev->type = SL_REQ_IN; + my_as_ev->len = len; + my_as_ev->transaction=seas_f.tmb.t_gett(); /*does not refcount*/ + if(use_stats) + as_relay_stat(seas_f.tmb.t_gett()); again: - ret=write(write_pipe,&my_as_ev,sizeof(as_msg_p)); - if(ret==-1){ - if(errno==EINTR) - goto again; - else if(errno==EPIPE){ - LM_ERR("SEAS Event Dispatcher has closed the pipe. Invalidating it !\n"); - return -2; - /** TODO handle this correctly !!!*/ - } - } - //this shouln't be here, because it will remove the transaction from memory, but - //if transaction isn't unref'ed iw will be released anyway at t_unref if kr (killreason)==0 - // a wait timer will be put to run with WT_TIME_OUT (5 seconds, within which the AS should respond) - // this is a bug !!! I think this is why we lose calls at high load !! - //t_release(msg, 0, 0); - /* seas_f.tmb.t_setkr(REQ_FWDED); */ - - ret=0; - return ret; + ret=write(write_pipe,&my_as_ev,sizeof(as_msg_p)); + if(ret==-1){ + if(errno==EINTR) + goto again; + else if(errno==EPIPE){ + LM_ERR("SEAS Event Dispatcher has closed the pipe. Invalidating it !\n"); + return -2; + /** TODO handle this correctly !!!*/ + } + } + //this shouln't be here, because it will remove the transaction from memory, but + //if transaction isn't unref'ed iw will be released anyway at t_unref if kr (killreason)==0 + // a wait timer will be put to run with WT_TIME_OUT (5 seconds, within which the AS should respond) + // this is a bug !!! I think this is why we lose calls at high load !! + //t_release(msg, 0, 0); + /* seas_f.tmb.t_setkr(REQ_FWDED); */ + + ret=0; + return ret; error: - if(my_as_ev) - shm_free(my_as_ev); - if(buffer) - shm_free(buffer); - return ret; + if(my_as_ev) + shm_free(my_as_ev); + if(buffer) + shm_free(buffer); + return ret; } /** * creates an as_event in shared memory and returns its address or NULL if error. * event_length(4) UNSIGNED INT includes the length 4 bytes itself - * type(1), + * type(1), * flags(4), * transport(1). - * src_ip_len(1), - * src_ip(4 or 16), - * dst_ip_len(1), - * dst_ip(4 or 16), - * src_port(2), - * dst_port(2), - * hash index(4), - * label(4), + * src_ip_len(1), + * src_ip(4 or 16), + * dst_ip_len(1), + * dst_ip(4 or 16), + * src_port(2), + * dst_port(2), + * hash index(4), + * label(4), * [cancelled hash_index,label] * */ char * create_as_event_t(struct cell *t,struct sip_msg *msg,char processor_id,int *evt_len,int flags) { - unsigned int i,hash_index,label; - unsigned short int port; - unsigned int k,len; - char *buffer=NULL; - struct cell *originalT; - - originalT=0; - - if(!(buffer=shm_malloc(ENCODED_MSG_SIZE))){ - LM_ERR("Out Of Memory !!\n"); - return 0; - } - *evt_len=0; - if(t){ - hash_index=t->hash_index; - label=t->label; - }else{ - /**seas_f.tmb.t_get_trans_ident(msg,&hash_index,&label); this is bad, because it ref-counts !!!*/ - LM_ERR("no transaction provided...\n"); - goto error; - } - - k=4; - /*type*/ - buffer[k++]=(unsigned char)T_REQ_IN; - /*processor_id*/ - buffer[k++]=(unsigned char)processor_id; - /*flags*/ - if(is_e2e_ack(t,msg)){ - flags|=E2E_ACK; - }else if(msg->REQ_METHOD==METHOD_CANCEL){ - LM_DBG("new CANCEL\n"); - originalT=seas_f.tmb.t_lookup_original(msg); - if(!originalT || originalT==T_UNDEFINED){ - /** we dont even pass the unknown CANCEL to JAIN*/ - LM_WARN("CANCEL does not match any existing transaction!!\n"); - goto error; - }else{ - flags|=CANCEL_FOUND; - //seas_f.tmb.unref_cell(originalT); - } - LM_DBG("Cancelling transaction !!\n"); - } - flags=htonl(flags); - memcpy(buffer+k,&flags,4); - k+=4; - /*protocol should be UDP,TCP,TLS or whatever*/ - buffer[k++]=(unsigned char)msg->rcv.proto; - /*src ip len + src ip*/ - len=msg->rcv.src_ip.len; - buffer[k++]=(unsigned char)len; - memcpy(buffer+k,&(msg->rcv.src_ip.u),len); - k+=len; - /*dst ip len + dst ip*/ - len=msg->rcv.dst_ip.len; - buffer[k++]=(unsigned char)len; - memcpy(buffer+k,&(msg->rcv.dst_ip.u),len); - k+=len; - /*src port */ - port=htons(msg->rcv.src_port); - memcpy(buffer+k,&port,2); - k+=2; - /*dst port */ - port=htons(msg->rcv.dst_port); - memcpy(buffer+k,&port,2); - k+=2; - /*hash_index*/ - i=htonl(hash_index); - memcpy(buffer+k,&i,4); - k+=4; - /*label (is the collision slot in the hash-table)*/ - i=htonl(label); - memcpy(buffer+k,&i,4); - k+=4; - if(msg->REQ_METHOD==METHOD_CANCEL && originalT){ - LM_DBG("Cancelled transaction: Hash_Index=%d, Label=%d\n",originalT->hash_index,originalT->label); - /*hash_index*/ - i=htonl(originalT->hash_index); - memcpy(buffer+k,&i,4); - k+=4; - /*label (is the collision slot in the hash-table)*/ - i=htonl(originalT->label); - memcpy(buffer+k,&i,4); - k+=4; - } - - /*length of event (hdr+payload-4), copied at the beginning*/ - if(encode_msg(msg,buffer+k,ENCODED_MSG_SIZE-k)<0){ - LM_ERR("Unable to encode msg\n"); - goto error; - } - i = GET_PAY_SIZE(buffer+k); - k+=i; - *evt_len=k; - k=htonl(k); - memcpy(buffer,&k,4); - return buffer; + unsigned int i,hash_index,label; + unsigned short int port; + unsigned int k,len; + char *buffer=NULL; + struct cell *originalT; + + originalT=0; + + if(!(buffer=shm_malloc(ENCODED_MSG_SIZE))){ + LM_ERR("Out Of Memory !!\n"); + return 0; + } + *evt_len=0; + if(t){ + hash_index=t->hash_index; + label=t->label; + }else{ + /**seas_f.tmb.t_get_trans_ident(msg,&hash_index,&label); this is bad, because it ref-counts !!!*/ + LM_ERR("no transaction provided...\n"); + goto error; + } + + k=4; + /*type*/ + buffer[k++]=(unsigned char)T_REQ_IN; + /*processor_id*/ + buffer[k++]=(unsigned char)processor_id; + /*flags*/ + if(is_e2e_ack(t,msg)){ + flags|=E2E_ACK; + }else if(msg->REQ_METHOD==METHOD_CANCEL){ + LM_DBG("new CANCEL\n"); + originalT=seas_f.tmb.t_lookup_original(msg); + if(!originalT || originalT==T_UNDEFINED){ + /** we dont even pass the unknown CANCEL to JAIN*/ + LM_WARN("CANCEL does not match any existing transaction!!\n"); + goto error; + }else{ + flags|=CANCEL_FOUND; + //seas_f.tmb.unref_cell(originalT); + } + LM_DBG("Cancelling transaction !!\n"); + } + flags=htonl(flags); + memcpy(buffer+k,&flags,4); + k+=4; + /*protocol should be UDP,TCP,TLS or whatever*/ + buffer[k++]=(unsigned char)msg->rcv.proto; + /*src ip len + src ip*/ + len=msg->rcv.src_ip.len; + buffer[k++]=(unsigned char)len; + memcpy(buffer+k,&(msg->rcv.src_ip.u),len); + k+=len; + /*dst ip len + dst ip*/ + len=msg->rcv.dst_ip.len; + buffer[k++]=(unsigned char)len; + memcpy(buffer+k,&(msg->rcv.dst_ip.u),len); + k+=len; + /*src port */ + port=htons(msg->rcv.src_port); + memcpy(buffer+k,&port,2); + k+=2; + /*dst port */ + port=htons(msg->rcv.dst_port); + memcpy(buffer+k,&port,2); + k+=2; + /*hash_index*/ + i=htonl(hash_index); + memcpy(buffer+k,&i,4); + k+=4; + /*label (is the collision slot in the hash-table)*/ + i=htonl(label); + memcpy(buffer+k,&i,4); + k+=4; + if(msg->REQ_METHOD==METHOD_CANCEL && originalT){ + LM_DBG("Cancelled transaction: Hash_Index=%d, Label=%d\n",originalT->hash_index,originalT->label); + /*hash_index*/ + i=htonl(originalT->hash_index); + memcpy(buffer+k,&i,4); + k+=4; + /*label (is the collision slot in the hash-table)*/ + i=htonl(originalT->label); + memcpy(buffer+k,&i,4); + k+=4; + } + + /*length of event (hdr+payload-4), copied at the beginning*/ + if(encode_msg(msg,buffer+k,ENCODED_MSG_SIZE-k)<0){ + LM_ERR("Unable to encode msg\n"); + goto error; + } + i = GET_PAY_SIZE(buffer+k); + k+=i; + *evt_len=k; + k=htonl(k); + memcpy(buffer,&k,4); + return buffer; error: - if(buffer) - shm_free(buffer); - return 0; + if(buffer) + shm_free(buffer); + return 0; } /** * creates an as_event in shared memory and returns its address or NULL if error. * event_length(4) UNSIGNED INT includes the length 4 bytes itself - * type(1), - * processor_id(4), + * type(1), + * processor_id(4), * flags(4), * transport(1). - * src_ip_len(1), - * src_ip(4 or 16), - * dst_ip_len(1), - * dst_ip(4 or 16), - * src_port(2), - * dst_port(2), + * src_ip_len(1), + * src_ip(4 or 16), + * dst_ip_len(1), + * dst_ip(4 or 16), + * src_port(2), + * dst_port(2), * */ char * create_as_event_sl(struct sip_msg *msg,char processor_id,int *evt_len,int flags) { - unsigned int i; - unsigned short int port; - unsigned int k,len; - char *buffer=NULL; - - if(!(buffer=shm_malloc(ENCODED_MSG_SIZE))){ - LM_ERR("create_as_event_t Out Of Memory !!\n"); - return 0; - } - *evt_len=0; - - /*leave 4 bytes for event length*/ - k=4; - /*type*/ - buffer[k++]=(unsigned char)SL_REQ_IN; - /*processor_id*/ - buffer[k++]=(unsigned char)processor_id; - /*flags*/ - flags=htonl(flags); - memcpy(buffer+k,&flags,4); - k+=4; - /*protocol should be UDP,TCP,TLS or whatever*/ - buffer[k++]=(unsigned char)msg->rcv.proto; - /*src ip len + src ip*/ - len=msg->rcv.src_ip.len; - buffer[k++]=(unsigned char)len; - memcpy(buffer+k,&(msg->rcv.src_ip.u),len); - k+=len; - /*dst ip len + dst ip*/ - len=msg->rcv.dst_ip.len; - buffer[k++]=(unsigned char)len; - memcpy(buffer+k,&(msg->rcv.dst_ip.u),len); - k+=len; - /*src port */ - port=htons(msg->rcv.src_port); - memcpy(buffer+k,&port,2); - k+=2; - /*dst port */ - port=htons(msg->rcv.dst_port); - memcpy(buffer+k,&port,2); - k+=2; - /*length of event (hdr+payload-4), copied at the beginning*/ - if(encode_msg(msg,buffer+k,ENCODED_MSG_SIZE-k)<0){ - LM_ERR("Unable to encode msg\n"); - goto error; - } - i = GET_PAY_SIZE(buffer+k); - k+=i; - *evt_len=k; - k=htonl(k); - memcpy(buffer,&k,4); - return buffer; + unsigned int i; + unsigned short int port; + unsigned int k,len; + char *buffer=NULL; + + if(!(buffer=shm_malloc(ENCODED_MSG_SIZE))){ + LM_ERR("create_as_event_t Out Of Memory !!\n"); + return 0; + } + *evt_len=0; + + /*leave 4 bytes for event length*/ + k=4; + /*type*/ + buffer[k++]=(unsigned char)SL_REQ_IN; + /*processor_id*/ + buffer[k++]=(unsigned char)processor_id; + /*flags*/ + flags=htonl(flags); + memcpy(buffer+k,&flags,4); + k+=4; + /*protocol should be UDP,TCP,TLS or whatever*/ + buffer[k++]=(unsigned char)msg->rcv.proto; + /*src ip len + src ip*/ + len=msg->rcv.src_ip.len; + buffer[k++]=(unsigned char)len; + memcpy(buffer+k,&(msg->rcv.src_ip.u),len); + k+=len; + /*dst ip len + dst ip*/ + len=msg->rcv.dst_ip.len; + buffer[k++]=(unsigned char)len; + memcpy(buffer+k,&(msg->rcv.dst_ip.u),len); + k+=len; + /*src port */ + port=htons(msg->rcv.src_port); + memcpy(buffer+k,&port,2); + k+=2; + /*dst port */ + port=htons(msg->rcv.dst_port); + memcpy(buffer+k,&port,2); + k+=2; + /*length of event (hdr+payload-4), copied at the beginning*/ + if(encode_msg(msg,buffer+k,ENCODED_MSG_SIZE-k)<0){ + LM_ERR("Unable to encode msg\n"); + goto error; + } + i = GET_PAY_SIZE(buffer+k); + k+=i; + *evt_len=k; + k=htonl(k); + memcpy(buffer,&k,4); + return buffer; error: - if(buffer) - shm_free(buffer); - return 0; + if(buffer) + shm_free(buffer); + return 0; } static inline int is_e2e_ack(struct cell *t,struct sip_msg *msg) { - if(msg->REQ_METHOD != METHOD_ACK) - return 0; - if (t->uas.status<300) - return 1; - return 0; + if(msg->REQ_METHOD != METHOD_ACK) + return 0; + if (t->uas.status<300) + return 1; + return 0; } /** Initializes seas module. It first parses the listen_sockets parameter @@ -626,75 +625,75 @@ static inline int is_e2e_ack(struct cell *t,struct sip_msg *msg) */ static int seas_init(void) { - char *p,*port; - struct hostent *he; - struct socket_info *si; - int c_pipe[2],mierr,i; - /** Populate seas_functions*/ - if (load_tm_api(&seas_f.tmb)!=0) { - LM_ERR( "can't load TM API\n"); - return -1; - } - if(!(seas_f.t_check_orig_trans = find_export("t_check_trans", 0, 0))){ - LM_ERR( "Seas requires transaction module (t_check_trans not found)\n"); - return -1; - } - /** Populate seas_functions*/ - c_pipe[0]=c_pipe[1]=-1; - p=seas_listen_socket; - port=(char *)0; - seas_listen_port=5080; - /*if the seas_listen_socket configuration string is empty, use default values*/ - if(p==NULL || *p==0){ - si=get_first_socket(); - seas_listen_ip=&si->address; - } else {/*if config string is not empty, then try to find host first, and maybe port..*/ - while(*p){ - if(*p == ':'){ - *p=0; - port=p+1; - break; - } - p++; - } - if(!(he=resolvehost(seas_listen_socket))) - goto error; - if(!(seas_listen_ip=pkg_malloc(sizeof(struct ip_addr)))) - goto error; - hostent2ip_addr(seas_listen_ip, he, 0); - if(port!=(char *)0 && (seas_listen_port=str2s(port,strlen(port),&mierr))==0){ - LM_ERR("invalid port %s \n",port); - goto error; - } - } - memset(unc_as_t,0,2*MAX_UNC_AS_NR*sizeof(struct unc_as));//useless because unc_as_t is in bss? - if (pipe(c_pipe)==-1) { - LM_ERR("cannot create pipe!\n"); - goto error; - } - read_pipe=c_pipe[0]; - write_pipe=c_pipe[1]; - seas_init_tags(); - if(0>start_stats_server(seas_stats_socket)) - goto error; - if(0>prepare_ha()) - goto error; - if(0>parse_cluster_cfg()) - goto error; - register_procs(1); + char *p,*port; + struct hostent *he; + struct socket_info *si; + int c_pipe[2],mierr,i; + /** Populate seas_functions*/ + if (load_tm_api(&seas_f.tmb)!=0) { + LM_ERR( "can't load TM API\n"); + return -1; + } + if(!(seas_f.t_check_orig_trans = find_export("t_check_trans", 0, 0))){ + LM_ERR( "Seas requires transaction module (t_check_trans not found)\n"); + return -1; + } + /** Populate seas_functions*/ + c_pipe[0]=c_pipe[1]=-1; + p=seas_listen_socket; + port=(char *)0; + seas_listen_port=5080; + /*if the seas_listen_socket configuration string is empty, use default values*/ + if(p==NULL || *p==0){ + si=get_first_socket(); + seas_listen_ip=&si->address; + } else {/*if config string is not empty, then try to find host first, and maybe port..*/ + while(*p){ + if(*p == ':'){ + *p=0; + port=p+1; + break; + } + p++; + } + if(!(he=resolvehost(seas_listen_socket))) + goto error; + if(!(seas_listen_ip=pkg_malloc(sizeof(struct ip_addr)))) + goto error; + hostent2ip_addr(seas_listen_ip, he, 0); + if(port!=(char *)0 && (seas_listen_port=str2s(port,strlen(port),&mierr))==0){ + LM_ERR("invalid port %s \n",port); + goto error; + } + } + memset(unc_as_t,0,2*MAX_UNC_AS_NR*sizeof(struct unc_as));//useless because unc_as_t is in bss? + if (pipe(c_pipe)==-1) { + LM_ERR("cannot create pipe!\n"); + goto error; + } + read_pipe=c_pipe[0]; + write_pipe=c_pipe[1]; + seas_init_tags(); + if(0>start_stats_server(seas_stats_socket)) + goto error; + if(0>prepare_ha()) + goto error; + if(0>parse_cluster_cfg()) + goto error; + register_procs(1); /* add child to update local config framework structures */ cfg_register_child(1); - return 0; + return 0; error: - for(i=0;i<2;i++) - if(c_pipe[i]!=-1) - close(c_pipe[i]); - if(seas_listen_ip!=0) - pkg_free(seas_listen_ip); - if(use_stats) - stop_stats_server(); - return -1; + for(i=0;i<2;i++) + if(c_pipe[i]!=-1) + close(c_pipe[i]); + if(seas_listen_ip!=0) + pkg_free(seas_listen_ip); + if(use_stats) + stop_stats_server(); + return -1; } @@ -702,8 +701,8 @@ static int seas_init(void) */ static void seas_init_tags(void) { - init_tags(seas_tags, &seas_tag_suffix,"VozTele-Seas/tags",'-'); - LM_DBG("seas_init_tags, seas_tags=%s\n",seas_tags); + init_tags(seas_tags, &seas_tag_suffix,"VozTele-Seas/tags",'-'); + LM_DBG("seas_init_tags, seas_tags=%s\n",seas_tags); } /** @@ -716,30 +715,30 @@ static void seas_init_tags(void) */ static int seas_child_init(int rank) { - int pid; - - /* only the child 1 will execute this */ - if (rank != PROC_MAIN){ - /* only dispatcher needs to read from the pipe, so close reading fd*/ - /*close(read_pipe);*/ - return 0; - } - if ((pid=fork_process(PROC_NOCHLDINIT,"SEAS",0))<0) { - LM_ERR("forking failed\n"); - return -1; - } - if (!pid) { - /*dispatcher child. we leave writing end open so that new childs spawned - * by event dispatcher can also write to pipe.. */ + int pid; + + /* only the child 1 will execute this */ + if (rank != PROC_MAIN){ + /* only dispatcher needs to read from the pipe, so close reading fd*/ + /*close(read_pipe);*/ + return 0; + } + if ((pid=fork_process(PROC_NOCHLDINIT,"SEAS",0))<0) { + LM_ERR("forking failed\n"); + return -1; + } + if (!pid) { + /*dispatcher child. we leave writing end open so that new childs spawned + * by event dispatcher can also write to pipe.. */ /* initialize the config framework */ if (cfg_child_init()) return -1; - /* close(write_pipe); */ - return dispatcher_main_loop(); - } - return 0; + /* close(write_pipe); */ + return dispatcher_main_loop(); + } + return 0; } /* this should close the sockets open to any of the application servers, and @@ -748,27 +747,27 @@ static int seas_child_init(int rank) */ static int seas_exit(void) { - if( seas_listen_ip!=NULL && seas_listen_ip!=&(get_first_socket()->address)) - pkg_free(seas_listen_ip); - return 0; + if( seas_listen_ip!=NULL && seas_listen_ip!=&(get_first_socket()->address)) + pkg_free(seas_listen_ip); + return 0; } /** * search within a given AS, if any of the registered processors is bound - * to the receive_info structure passed. If there is one, it returns its + * to the receive_info structure passed. If there is one, it returns its * identifier (number between 0 and 128), otherwise it returns -1; */ char get_processor_id(struct receive_info *rcv,as_p as) { - int i; - for(i=0;ibound_processor[i]!=0 && - (rcv->dst_ip.len == as->binds[i]->address.len) && - (rcv->dst_ip.af==as->binds[i]->address.af) && - (!memcmp(rcv->dst_ip.u.addr,as->binds[i]->address.u.addr,rcv->dst_ip.len))/* && - (rcv->dst_port==as->binds[i].dst_port) && - (rcv->proto==as->binds[i].proto)*/) - return as->bound_processor[i]; - } - return -1; + int i; + for(i=0;ibound_processor[i]!=0 && + (rcv->dst_ip.len == as->binds[i]->address.len) && + (rcv->dst_ip.af==as->binds[i]->address.af) && + (!memcmp(rcv->dst_ip.u.addr,as->binds[i]->address.u.addr,rcv->dst_ip.len))/* && + (rcv->dst_port==as->binds[i].dst_port) && + (rcv->proto==as->binds[i].proto)*/) + return as->bound_processor[i]; + } + return -1; } diff --git a/src/modules/seas/seas.h b/src/modules/seas/seas.h index 6a7c03a0c18..9f525f48c40 100644 --- a/src/modules/seas/seas.h +++ b/src/modules/seas/seas.h @@ -1,5 +1,4 @@ -/* $Id$ - * +/* * Copyright (C) 2006-2007 VozTelecom Sistemas S.L * * This file is part of Kamailio, a free SIP server. @@ -14,8 +13,8 @@ * 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 + * 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 */ @@ -67,9 +66,9 @@ #define SPIRAL_FLAG 0x00000001 #define net2hostL(dst,from,index) do{ \ - memcpy(&(dst),(from)+(index),4); \ - dst=ntohl(dst); \ - (index)+=4; \ + memcpy(&(dst),(from)+(index),4); \ + dst=ntohl(dst); \ + (index)+=4; \ }while(0); @@ -94,32 +93,32 @@ extern int servlet_pings_lost; extern struct as_entry *as_table; struct seas_functions{ - struct tm_binds tmb; - cmd_function t_check_orig_trans; + struct tm_binds tmb; + cmd_function t_check_orig_trans; }; /*TODO listen_points should be dynamically allocated ?*/ typedef struct app_server { - int event_fd; - int action_fd; - str name; - pid_t action_pid; - struct socket_info *binds[MAX_BINDS]; - char bound_processor[MAX_BINDS]; - int num_binds; - str ev_buffer; - str ac_buffer; - struct ha jain_pings; - struct ha servlet_pings; - struct cluster *cluster; + int event_fd; + int action_fd; + str name; + pid_t action_pid; + struct socket_info *binds[MAX_BINDS]; + char bound_processor[MAX_BINDS]; + int num_binds; + str ev_buffer; + str ac_buffer; + struct ha jain_pings; + struct ha servlet_pings; + struct cluster *cluster; }as_t, *as_p; struct cluster{ - str name; - int num; - int registered; - str as_names[MAX_AS_PER_CLUSTER]; - as_p servers[MAX_AS_PER_CLUSTER]; + str name; + int num; + int registered; + str as_names[MAX_AS_PER_CLUSTER]; + as_p servers[MAX_AS_PER_CLUSTER]; }; /** @@ -127,32 +126,32 @@ struct cluster{ * when one matches, they will put the as pointer inside the event that should process * that event. * If eventually the as becomes unavailable, the dispatcher will set valid=false, which should be - * atomic operation. This way, we prevent having to put a mutex on the array, which would make + * atomic operation. This way, we prevent having to put a mutex on the array, which would make * it slower , as only one process could be accessing it at a time. */ struct as_entry{ - str name; - int type; - int connected; - union{ - struct app_server as; - struct cluster cs; - }u; - struct as_entry *next; + str name; + int type; + int connected; + union{ + struct app_server as; + struct cluster cs; + }u; + struct as_entry *next; }; extern struct as_entry *my_as; -extern struct seas_functions seas_f; +extern struct seas_functions seas_f; extern struct as_entry *as_list; typedef struct as_msg { - struct cell *transaction; - char *msg; - int len; - int type; - int id; - struct as_entry *as; + struct cell *transaction; + char *msg; + int len; + int type; + int id; + struct as_entry *as; }as_msg_t,*as_msg_p; char get_processor_id(struct receive_info *rcv,as_p as); @@ -162,17 +161,17 @@ char* create_as_event_sl(struct sip_msg *msg,char processor_id,int *evt_len,int static inline void print_ip_buf(struct ip_addr* ip, char *where,int len) { - switch(ip->af){ - case AF_INET: - snprintf(where,len,"%d.%d.%d.%d", ip->u.addr[0], ip->u.addr[1], ip->u.addr[2], ip->u.addr[3]); - break; - case AF_INET6: - snprintf(where,len,"%x:%x:%x:%x:%x:%x:%x:%x",htons(ip->u.addr16[0]),htons(ip->u.addr16[1]),htons(ip->u.addr16[2]), - htons(ip->u.addr16[3]), htons(ip->u.addr16[4]), htons(ip->u.addr16[5]), htons(ip->u.addr16[6]), - htons(ip->u.addr16[7])); - break; - default: - break; - } + switch(ip->af){ + case AF_INET: + snprintf(where,len,"%d.%d.%d.%d", ip->u.addr[0], ip->u.addr[1], ip->u.addr[2], ip->u.addr[3]); + break; + case AF_INET6: + snprintf(where,len,"%x:%x:%x:%x:%x:%x:%x:%x",htons(ip->u.addr16[0]),htons(ip->u.addr16[1]),htons(ip->u.addr16[2]), + htons(ip->u.addr16[3]), htons(ip->u.addr16[4]), htons(ip->u.addr16[5]), htons(ip->u.addr16[6]), + htons(ip->u.addr16[7])); + break; + default: + break; + } } #endif diff --git a/src/modules/seas/seas_action.c b/src/modules/seas/seas_action.c index 3cb5513fbd1..7c963e6fe7a 100644 --- a/src/modules/seas/seas_action.c +++ b/src/modules/seas/seas_action.c @@ -1,5 +1,4 @@ -/* $Id$ - * +/* * Copyright (C) 2006-2007 VozTelecom Sistemas S.L * * This file is part of Kamailio, a free SIP server. @@ -14,15 +13,10 @@ * 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 + * 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 * - * History: - * ------- - * 2008-04-04 added support for local and remote dispaly name in TM dialogs - * (by Andrei Pisau ) - * */ #include @@ -496,7 +490,7 @@ int ac_cancel(as_p the_as,unsigned char processor_id,unsigned int flags,char *ac the_param->uac_id=uac_id; the_param->processor_id=processor_id; the_param->destroy_cb_set=0; - + /* registers TMCB_RESPONSE_IN|TMCB_LOCAL_COMPLETED tm callbacks */ ret=seas_f.tmb.t_cancel_uac(&headers,&body,cancelled_hashIdx,cancelled_label,uac_cb,(void*)the_param); if (ret == 0) { @@ -901,15 +895,15 @@ int forward_sl_request(struct sip_msg *msg,str *uri,int proto) if ((uri2dst(NULL,&dst, msg, uri, proto)==0) || (dst.send_sock==0)) #else if ((uri2dst(&dst, msg, uri, proto)==0) || (dst.send_sock==0)) -#endif +#endif { - LOG(L_ERR, "forward_sl_request: no socket found\n"); + LM_ERR("no socket found\n"); return -1; } LM_DBG("Sending:\n%.*s.\n", (int)msg->len,msg->buf); if (msg_send(&dst, msg->buf,msg->len)<0){ - LM_ERR("ERROR:seas:forward_sl_request: Error sending message !!\n"); + LM_ERR("Error sending message !!\n"); return -1; } return ret; diff --git a/src/modules/tm/README b/src/modules/tm/README index bec0630d959..bd10d0d7790 100644 --- a/src/modules/tm/README +++ b/src/modules/tm/README @@ -140,6 +140,7 @@ Daniel-Constantin Mierla 5.5. tm.hash_stats 5.6. tm.reply 5.7. tm.reply_callid + 5.8. tm.clean 6. Event Routes @@ -379,6 +380,7 @@ Chapter 1. Admin Guide 5.5. tm.hash_stats 5.6. tm.reply 5.7. tm.reply_callid + 5.8. tm.clean 6. Event Routes @@ -2806,6 +2808,7 @@ t_uac_send("OPTIONS", "sip:alice@kamailio.org", "", "", 5.5. tm.hash_stats 5.6. tm.reply 5.7. tm.reply_callid + 5.8. tm.clean 5.1. tm.list @@ -2878,6 +2881,13 @@ t_uac_send("OPTIONS", "sip:alice@kamailio.org", "", "", * body - (optional, may not be present) reply body (if present, requires the “Content-Type” and “Content-length” headers) +5.8. tm.clean + + Trigger an hard clean of expired transactions. + + Parameters: + * none + 6. Event Routes 6.1. event_route[tm:branch-failure] diff --git a/src/modules/tm/doc/rpc.xml b/src/modules/tm/doc/rpc.xml index bc3fe332c5b..efc445cbee2 100644 --- a/src/modules/tm/doc/rpc.xml +++ b/src/modules/tm/doc/rpc.xml @@ -177,5 +177,19 @@
+
+ + <function moreinfo="none">tm.clean</function> + + + Trigger an hard clean of expired transactions. + + Parameters: + + + none + + +
diff --git a/src/modules/tm/h_table.c b/src/modules/tm/h_table.c index 19b5daec0bb..ee79b91fd3f 100644 --- a/src/modules/tm/h_table.c +++ b/src/modules/tm/h_table.c @@ -575,3 +575,62 @@ void tm_xdata_replace(tm_xdata_t *newxd, tm_xlinks_t *bakxd) return; } } + +void tm_log_transaction(tm_cell_t *tcell, int llev, char *ltext) +{ + LOG(llev, "%s [start] transaction %p\n", ltext, tcell); + LOG(llev, "%s - tindex=%u tlabel=%u method='%.*s' from='%.*s'" + " to='%.*s' callid='%.*s' cseq='%.*s' uas_request=%s" + " tflags=%u outgoings=%u ref_count=%u lifetime=%u\n", + ltext, (unsigned)tcell->hash_index, (unsigned)tcell->label, + tcell->method.len, tcell->method.s, + tcell->from.len, tcell->from.s, + tcell->to.len, tcell->to.s, + tcell->callid.len, tcell->callid.s, + tcell->cseq_n.len, tcell->cseq_n.s, + (tcell->uas.request)?"yes":"no", + (unsigned)tcell->flags, + (unsigned)tcell->nr_of_outgoings, +#ifdef TM_DEL_UNREF + (unsigned)atomic_get(&tcell->ref_count), +#else + tcell->ref_count, +#endif + (unsigned)TICKS_TO_S(tcell->end_of_life) + ); + + LOG(llev, "%s [end] transaction %p\n", ltext, tcell); +} + +#define TM_LIFETIME_LIMIT 90 +/* clean active but very old transactions */ +void tm_clean_lifetime(void) +{ + int r; + tm_cell_t *tcell; + ticks_t texp; + + texp = get_ticks_raw() - S_TO_TICKS(TM_LIFETIME_LIMIT); + + for (r=0; rentries[r], next_c)) { + continue; + } + lock_hash(r); + /* one more time with lock to be avoid any cpu races */ + if(clist_empty(&_tm_table->entries[r], next_c)) { + unlock_hash(r); + continue; + } + + clist_foreach(&_tm_table->entries[r], tcell, next_c) + { + if(TICKS_GT(texp, tcell->end_of_life)) { + tm_log_transaction(tcell, L_WARN, "[hard cleanup]"); + free_cell(tcell); + } + } + unlock_hash(r); + } +} diff --git a/src/modules/tm/h_table.h b/src/modules/tm/h_table.h index 904709579af..7d61ae36730 100644 --- a/src/modules/tm/h_table.h +++ b/src/modules/tm/h_table.h @@ -607,6 +607,8 @@ inline static void remove_from_hash_table_unsafe(struct cell *p_cell) t_stats_deleted(is_local(p_cell)); } +void tm_clean_lifetime(void); + /** * backup xdata from/to msg context to local var and use T lists */ diff --git a/src/modules/tm/t_stats.c b/src/modules/tm/t_stats.c index d6ae5f52e4a..6b26aedba00 100644 --- a/src/modules/tm/t_stats.c +++ b/src/modules/tm/t_stats.c @@ -252,7 +252,7 @@ void tm_rpc_hash_stats(rpc_t* rpc, void* c) #endif /* TM_HASH_STATS */ } -/* hash statistics */ +/* list active transactions */ void tm_rpc_list(rpc_t* rpc, void* c) { int r; @@ -294,3 +294,10 @@ void tm_rpc_list(rpc_t* rpc, void* c) unlock_hash(r); } } + + +/* rpc command to clean active but very old transactions */ +void tm_rpc_clean(rpc_t* rpc, void* c) +{ + tm_clean_lifetime(); +} diff --git a/src/modules/tm/t_stats.h b/src/modules/tm/t_stats.h index 0a0057c6203..bd21befd0fd 100644 --- a/src/modules/tm/t_stats.h +++ b/src/modules/tm/t_stats.h @@ -150,5 +150,6 @@ void tm_rpc_hash_stats(rpc_t* rpc, void* c); typedef int (*tm_get_stats_f)(struct t_proc_stats *all); int tm_get_stats(struct t_proc_stats *all); void tm_rpc_list(rpc_t* rpc, void* c); +void tm_rpc_clean(rpc_t* rpc, void* c); #endif diff --git a/src/modules/tm/tm.c b/src/modules/tm/tm.c index 7adaa8796d0..9bc1695a0f8 100644 --- a/src/modules/tm/tm.c +++ b/src/modules/tm/tm.c @@ -2521,6 +2521,11 @@ static const char* tm_rpc_list_doc[2] = { 0 }; +static const char* tm_rpc_clean_doc[2] = { + "Clean expired (lifetime exceeded) transactions.", + 0 +}; + /* rpc exports */ static rpc_export_t tm_rpc[] = { @@ -2532,6 +2537,7 @@ static rpc_export_t tm_rpc[] = { {"tm.t_uac_start", rpc_t_uac_start, rpc_t_uac_start_doc, 0 }, {"tm.t_uac_wait", rpc_t_uac_wait, rpc_t_uac_wait_doc, RET_ARRAY}, {"tm.list", tm_rpc_list, tm_rpc_list_doc, RET_ARRAY}, + {"tm.clean", tm_rpc_clean, tm_rpc_clean_doc, 0}, {0, 0, 0, 0} }; diff --git a/src/modules/uid_auth_db/aaa_avps.h b/src/modules/uid_auth_db/aaa_avps.h index 21f9954097d..62f1062bf3d 100644 --- a/src/modules/uid_auth_db/aaa_avps.h +++ b/src/modules/uid_auth_db/aaa_avps.h @@ -39,8 +39,8 @@ * Parse list of tokens separated by some char and put each token * into result array. Caller frees result array! */ -static inline int -parse_token_list(char *p, char *pend, char separator, str **result) +static inline int parse_token_list(char *p, char *pend, char separator, + str **result) { int i; @@ -63,29 +63,27 @@ parse_token_list(char *p, char *pend, char separator, str **result) * Parse the list of AVP names separated by '|' into an array * of names, each element of the array is str string */ -static int -aaa_avps_init(str *avp_list, str **parsed_avps, int *avps_n) +static int aaa_avps_init(str *avp_list, str **parsed_avps, int *avps_n) { int errcode, i; char *cp; if (!avp_list->s || !avp_list->len) { - /* AVPs disabled, nothing to do */ + /* AVPs disabled, nothing to do */ *avps_n = 0; return 1; } cp = pkg_malloc(avp_list->len + 1); if (cp == NULL) { - LOG(L_ERR, "aaa_avps::aaa_avps_init(): can't allocate memory\n"); + LM_ERR("can't allocate memory\n"); errcode = -1; goto bad; } memcpy(cp, avp_list->s, avp_list->len); *avps_n = parse_token_list(cp, cp + avp_list->len, '|', parsed_avps); if (*avps_n == -1) { - LOG(L_ERR, "aaa_avps::aaa_avps_init(): can't parse avps_column_int " - "parameter\n"); + LM_ERR("can't parse avps_column_int parameter\n"); errcode = -2; pkg_free(cp); goto bad; diff --git a/src/modules/uid_auth_db/authorize.c b/src/modules/uid_auth_db/authorize.c index cc3e9807079..0dd155adda9 100644 --- a/src/modules/uid_auth_db/authorize.c +++ b/src/modules/uid_auth_db/authorize.c @@ -1,6 +1,4 @@ /* - * $Id$ - * * Digest Authentication - Database support * * Copyright (C) 2001-2003 FhG Fokus @@ -22,16 +20,10 @@ * 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 + * 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 * - * history: - * --------- - * 2003-02-28 scratchpad compatibility abandoned - * 2003-01-27 next baby-step to removing ZT - PRESERVE_ZT (jiri) - * 2004-06-06 updated to the new DB api, added auth_db_{init,bind,close,ver} - * (andrei) */ @@ -57,31 +49,31 @@ #define IS_NULL(f) ((f).flags & DB_NULL) static inline int get_ha1(struct username* username, str* did, str* realm, - authdb_table_info_t *table_info, char* ha1, db_res_t** res, db_rec_t** row) + authdb_table_info_t *table_info, char* ha1, db_res_t** res, db_rec_t** row) { str result; db_cmd_t *q = NULL; - + if (calc_ha1) { q = table_info->query_password; - DBG("querying plain password\n"); + LM_DBG("querying plain password\n"); } else { if (username->domain.len) { q = table_info->query_pass2; - DBG("querying ha1b\n"); + LM_DBG("querying ha1b\n"); } else { q = table_info->query_pass; - DBG("querying ha1\n"); + LM_DBG("querying ha1\n"); } } - + q->match[0].v.lstr = username->user; q->match[1].v.lstr = *realm; if (use_did) q->match[2].v.lstr = *did; if (db_exec(res, q) < 0 ) { - ERR("Error while querying database\n"); + LM_ERR("Error while querying database\n"); return -1; } @@ -89,8 +81,10 @@ static inline int get_ha1(struct username* username, str* did, str* realm, else *row = NULL; while (*row) { if (IS_NULL((*row)->fld[0]) || IS_NULL((*row)->fld[1])) { - LOG(L_ERR, "auth_db:get_ha1: Credentials for '%.*s'@'%.*s' contain NULL value, skipping\n", - username->user.len, ZSW(username->user.s), realm->len, ZSW(realm->s)); + LM_ERR("Credentials for '%.*s'@'%.*s' contain NULL value," + " skipping\n", + username->user.len, ZSW(username->user.s), + realm->len, ZSW(realm->s)); } else { if ((*row)->fld[1].v.int4 & SRDB_DISABLED) { /* disabled rows ignored */ @@ -105,10 +99,11 @@ static inline int get_ha1(struct username* username, str* did, str* realm, } if (!*row) { - DBG("auth_db:get_ha1: Credentials for '%.*s'@'%.*s' not found\n", - username->user.len, ZSW(username->user.s), realm->len, ZSW(realm->s)); + LM_DBG("Credentials for '%.*s'@'%.*s' not found\n", + username->user.len, ZSW(username->user.s), + realm->len, ZSW(realm->s)); return 1; - } + } result.s = (*row)->fld[0].v.cstr; result.len = strlen(result.s); @@ -117,7 +112,7 @@ static inline int get_ha1(struct username* username, str* did, str* realm, /* Only plaintext passwords are stored in database, * we have to calculate HA1 */ auth_api.calc_HA1(HA_MD5, &username->whole, realm, &result, 0, 0, ha1); - DBG("auth_db:get_ha1: HA1 string calculated: %s\n", ha1); + LM_DBG("HA1 string calculated: %s\n", ha1); } else { memcpy(ha1, result.s, result.len); ha1[result.len] = '\0'; @@ -133,36 +128,36 @@ static inline int get_ha1(struct username* username, str* did, str* realm, static inline int check_response(dig_cred_t* cred, str* method, char* ha1) { HASHHEX resp, hent; - + /* * First, we have to verify that the response received has * the same length as responses created by us */ if (cred->response.len != 32) { - DBG("auth_db:check_response: Receive response len != 32\n"); + LM_DBG("Receive response len != 32\n"); return 1; } - + /* * Now, calculate our response from parameters received * from the user agent */ - auth_api.calc_response(ha1, &(cred->nonce), - &(cred->nc), &(cred->cnonce), - &(cred->qop.qop_str), cred->qop.qop_parsed == QOP_AUTHINT, - method, &(cred->uri), hent, resp); - - DBG("auth_db:check_response: Our result = \'%s\'\n", resp); - + auth_api.calc_response(ha1, &(cred->nonce), + &(cred->nc), &(cred->cnonce), + &(cred->qop.qop_str), cred->qop.qop_parsed == QOP_AUTHINT, + method, &(cred->uri), hent, resp); + + LM_DBG("Our result = \'%s\'\n", resp); + /* * And simply compare the strings, the user is * authorized if they match */ if (!memcmp(resp, cred->response.s, 32)) { - DBG("auth_db:check_response: Authorization is OK\n"); + LM_DBG("Authorization is OK\n"); return 0; } else { - DBG("auth_db:check_response: Authorization failed\n"); + LM_DBG("Authorization failed\n"); return 2; } } @@ -177,7 +172,7 @@ static int generate_avps(db_res_t* result, db_rec_t *row) int_str iname, ivalue; str value; char buf[32]; - + for (i = 2; i < credentials_n + 2; i++) { value = row->fld[i].v.lstr; @@ -185,18 +180,18 @@ static int generate_avps(db_res_t* result, db_rec_t *row) continue; switch (row->fld[i].type) { - case DB_STR: - value = row->fld[i].v.lstr; - break; - - case DB_INT: - value.len = sprintf(buf, "%d", row->fld[i].v.int4); - value.s = buf; - break; - - default: - abort(); - break; + case DB_STR: + value = row->fld[i].v.lstr; + break; + + case DB_INT: + value.len = sprintf(buf, "%d", row->fld[i].v.int4); + value.s = buf; + break; + + default: + abort(); + break; } if (value.s == NULL) @@ -205,15 +200,16 @@ static int generate_avps(db_res_t* result, db_rec_t *row) iname.s = credentials[i - 2]; ivalue.s = value; - if (add_avp(AVP_NAME_STR | AVP_VAL_STR | AVP_CLASS_USER, iname, ivalue) < 0) { - LOG(L_ERR, "auth_db:generate_avps: Error while creating AVPs\n"); + if (add_avp(AVP_NAME_STR | AVP_VAL_STR | AVP_CLASS_USER, + iname, ivalue) < 0) { + LM_ERR("Error while creating AVPs\n"); return -1; } - DBG("auth_db:generate_avps: set string AVP \'%.*s = %.*s\'\n", - iname.s.len, ZSW(iname.s.s), value.len, ZSW(value.s)); + LM_DBG("set string AVP \'%.*s = %.*s\'\n", + iname.s.len, ZSW(iname.s.s), value.len, ZSW(value.s)); } - + return 0; } @@ -226,32 +222,32 @@ static int generate_avps(db_res_t* result, db_rec_t *row) * WARNING: if -1 is returned res _must_ _not_ be freed (it's empty) * */ -static inline int check_all_ha1(struct sip_msg* msg, struct hdr_field* hdr, - dig_cred_t* dig, str* method, str* did, str* realm, - authdb_table_info_t *table_info, db_res_t** res) +static inline int check_all_ha1(struct sip_msg* msg, struct hdr_field* hdr, + dig_cred_t* dig, str* method, str* did, str* realm, + authdb_table_info_t *table_info, db_res_t** res) { char ha1[256]; db_rec_t *row; str result; db_cmd_t *q; - + if (calc_ha1) { q = table_info->query_password; - DBG("querying plain password\n"); + LM_DBG("querying plain password\n"); } else { - if (dig->username.domain.len) { + if (dig->username.domain.len) { q = table_info->query_pass2; - DBG("querying ha1b\n"); + LM_DBG("querying ha1b\n"); } else { q = table_info->query_pass; - DBG("querying ha1\n"); + LM_DBG("querying ha1\n"); } } - + q->match[0].v.lstr = dig->username.user; - if (dig->username.domain.len) + if (dig->username.domain.len) q->match[1].v.lstr = dig->username.domain; else q->match[1].v.lstr = *realm; @@ -259,15 +255,17 @@ static inline int check_all_ha1(struct sip_msg* msg, struct hdr_field* hdr, if (use_did) q->match[2].v.lstr = *did; if (db_exec(res, q) < 0 ) { - ERR("Error while querying database\n"); + LM_ERR("Error while querying database\n"); } if (*res) row = db_first(*res); else row = NULL; while (row) { if (IS_NULL(row->fld[0]) || IS_NULL(row->fld[1])) { - LOG(L_ERR, "auth_db:check_all_ha1: Credentials for '%.*s'@'%.*s' contain NULL value, skipping\n", - dig->username.user.len, ZSW(dig->username.user.s), realm->len, ZSW(realm->s)); + LM_ERR("Credentials for '%.*s'@'%.*s' contain NULL value," + " skipping\n", + dig->username.user.len, ZSW(dig->username.user.s), + realm->len, ZSW(realm->s)); } else { if (row->fld[1].v.int4 & SRDB_DISABLED) { @@ -278,17 +276,19 @@ static inline int check_all_ha1(struct sip_msg* msg, struct hdr_field* hdr, result.s = row->fld[0].v.cstr; result.len = strlen(result.s); if (calc_ha1) { - /* Only plaintext passwords are stored in database, - * we have to calculate HA1 */ - auth_api.calc_HA1(HA_MD5, &(dig->username.whole), realm, &result, 0, 0, ha1); - DBG("auth_db:check_all_ha1: HA1 string calculated: %s\n", ha1); + /* Only plaintext passwords are stored in database, + * we have to calculate HA1 */ + auth_api.calc_HA1(HA_MD5, &(dig->username.whole), + realm, &result, 0, 0, ha1); + LM_DBG("HA1 string calculated: %s\n", ha1); } else { memcpy(ha1, result.s, result.len); ha1[result.len] = '\0'; } if (!check_response(dig, method, ha1)) { - if (auth_api.post_auth(msg, hdr, ha1) == AUTHENTICATED) { + if (auth_api.post_auth(msg, hdr, ha1) + == AUTHENTICATED) { generate_avps(*res, row); return 0; } @@ -300,9 +300,10 @@ static inline int check_all_ha1(struct sip_msg* msg, struct hdr_field* hdr, } if (!row) { - DBG("auth_db:check_all_ha1: Credentials for '%.*s'@'%.*s' not found", - dig->username.user.len, ZSW(dig->username.user.s), realm->len, ZSW(realm->s)); - } + LM_DBG("Credentials for '%.*s'@'%.*s' not found", + dig->username.user.len, ZSW(dig->username.user.s), + realm->len, ZSW(realm->s)); + } return 1; @@ -317,7 +318,8 @@ static inline int check_all_ha1(struct sip_msg* msg, struct hdr_field* hdr, * -1 -- Authentication failed * 1 -- Authentication successful */ -static inline int authenticate(struct sip_msg* msg, str* realm, authdb_table_info_t *table, hdr_types_t hftype) +static inline int authenticate(struct sip_msg* msg, str* realm, + authdb_table_info_t *table, hdr_types_t hftype) { char ha1[256]; int res, ret; @@ -326,51 +328,51 @@ static inline int authenticate(struct sip_msg* msg, str* realm, authdb_table_inf auth_body_t* cred; db_res_t* result; str did; - + cred = 0; result = 0; ret = -1; - + switch(auth_api.pre_auth(msg, realm, hftype, &h, NULL)) { - case NONCE_REUSED: - LM_DBG("nonce reused"); - ret = AUTH_NONCE_REUSED; - goto end; - case STALE_NONCE: - LM_DBG("stale nonce\n"); - ret = AUTH_STALE_NONCE; - goto end; - case NO_CREDENTIALS: - LM_DBG("no credentials\n"); - ret = AUTH_NO_CREDENTIALS; - goto end; - case ERROR: - case BAD_CREDENTIALS: - ret = -3; - goto end; - case CREATE_CHALLENGE: - ERR("auth_db:authenticate: CREATE_CHALLENGE is not a valid state\n"); - ret = -2; - goto end; - case DO_RESYNCHRONIZATION: - ERR("auth_db:authenticate: DO_RESYNCHRONIZATION is not a valid state\n"); - ret = -2; - goto end; - - case NOT_AUTHENTICATED: - ret = -1; - goto end; - - case DO_AUTHENTICATION: - break; - - case AUTHENTICATED: - ret = 1; - goto end; + case NONCE_REUSED: + LM_DBG("nonce reused"); + ret = AUTH_NONCE_REUSED; + goto end; + case STALE_NONCE: + LM_DBG("stale nonce\n"); + ret = AUTH_STALE_NONCE; + goto end; + case NO_CREDENTIALS: + LM_DBG("no credentials\n"); + ret = AUTH_NO_CREDENTIALS; + goto end; + case ERROR: + case BAD_CREDENTIALS: + ret = -3; + goto end; + case CREATE_CHALLENGE: + LM_ERR("CREATE_CHALLENGE is not a valid state\n"); + ret = -2; + goto end; + case DO_RESYNCHRONIZATION: + LM_ERR("DO_RESYNCHRONIZATION is not a valid state\n"); + ret = -2; + goto end; + + case NOT_AUTHENTICATED: + ret = -1; + goto end; + + case DO_AUTHENTICATION: + break; + + case AUTHENTICATED: + ret = 1; + goto end; } - + cred = (auth_body_t*)h->parsed; - + if (use_did) { if (msg->REQ_METHOD == METHOD_REGISTER) { ret = get_to_did(&did, msg); @@ -384,11 +386,12 @@ static inline int authenticate(struct sip_msg* msg, str* realm, authdb_table_inf } else { did.len = 0; did.s = 0; - } - + } + if (check_all) { - res = check_all_ha1(msg, h, &(cred->digest), &msg->first_line.u.request.method, &did, realm, table, &result); + res = check_all_ha1(msg, h, &(cred->digest), + &msg->first_line.u.request.method, &did, realm, table, &result); if (res < 0) { ret = -2; goto end; @@ -401,8 +404,9 @@ static inline int authenticate(struct sip_msg* msg, str* realm, authdb_table_inf ret = 1; goto end; } - } else { - res = get_ha1(&cred->digest.username, &did, realm, table, ha1, &result, &row); + } else { + res = get_ha1(&cred->digest.username, &did, realm, table, ha1, + &result, &row); if (res < 0) { ret = -2; goto end; @@ -411,39 +415,41 @@ static inline int authenticate(struct sip_msg* msg, str* realm, authdb_table_inf /* Username not found in the database */ ret = -1; goto end; - } - } - + } + } + /* Recalculate response, it must be same to authorize successfully */ - if (!check_response(&(cred->digest), &msg->first_line.u.request.method, ha1)) { + if (!check_response(&(cred->digest), &msg->first_line.u.request.method, + ha1)) { switch(auth_api.post_auth(msg, h, ha1)) { - case ERROR: - case BAD_CREDENTIALS: - ret = -2; - break; - - case NOT_AUTHENTICATED: - ret = -1; - break; - - case AUTHENTICATED: - generate_avps(result, row); - ret = 1; - break; - - default: - ret = -1; - break; + case ERROR: + case BAD_CREDENTIALS: + ret = -2; + break; + + case NOT_AUTHENTICATED: + ret = -1; + break; + + case AUTHENTICATED: + generate_avps(result, row); + ret = 1; + break; + + default: + ret = -1; + break; } } else { ret = -1; } - end: +end: if (result) db_res_free(result); if (ret < 0) { - if (auth_api.build_challenge(msg, (cred ? cred->stale : 0), realm, NULL, NULL, hftype) < 0) { - ERR("Error while creating challenge\n"); + if (auth_api.build_challenge(msg, (cred ? cred->stale : 0), realm, + NULL, NULL, hftype) < 0) { + LM_ERR("Error while creating challenge\n"); ret = -2; } } @@ -459,7 +465,8 @@ int proxy_authenticate(struct sip_msg* msg, char* p1, char* p2) str realm; if (get_str_fparam(&realm, msg, (fparam_t*)p1) < 0) { - ERR("Cannot obtain digest realm from parameter '%s'\n", ((fparam_t*)p1)->orig); + LM_ERR("Cannot obtain digest realm from parameter '%s'\n", + ((fparam_t*)p1)->orig); return -1; } @@ -475,9 +482,11 @@ int www_authenticate(struct sip_msg* msg, char* p1, char* p2) str realm; if (get_str_fparam(&realm, msg, (fparam_t*)p1) < 0) { - ERR("Cannot obtain digest realm from parameter '%s'\n", ((fparam_t*)p1)->orig); + LM_ERR("Cannot obtain digest realm from parameter '%s'\n", + ((fparam_t*)p1)->orig); return -1; } - return authenticate(msg, &realm, (authdb_table_info_t*)p2, HDR_AUTHORIZATION_T); + return authenticate(msg, &realm, (authdb_table_info_t*)p2, + HDR_AUTHORIZATION_T); } diff --git a/src/modules/uid_auth_db/authorize.h b/src/modules/uid_auth_db/authorize.h index d0f2a07d2f7..dbda474d5ca 100644 --- a/src/modules/uid_auth_db/authorize.h +++ b/src/modules/uid_auth_db/authorize.h @@ -1,6 +1,4 @@ /* - * $Id$ - * * Digest Authentication - Database support * * Copyright (C) 2001-2003 FhG Fokus @@ -22,8 +20,8 @@ * 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 + * 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 */ diff --git a/src/modules/uid_auth_db/uid_auth_db_mod.c b/src/modules/uid_auth_db/uid_auth_db_mod.c index 56ee952cea9..d67e40806a0 100644 --- a/src/modules/uid_auth_db/uid_auth_db_mod.c +++ b/src/modules/uid_auth_db/uid_auth_db_mod.c @@ -1,6 +1,4 @@ /* - * $Id$ - * * Digest Authentication Module * * Copyright (C) 2001-2003 FhG Fokus @@ -26,14 +24,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * - * History: - * -------- - * 2003-02-26: checks and group moved to separate modules (janakj) - * 2003-03-11: New module interface (janakj) - * 2003-03-16: flags export parameter added (janakj) - * 2003-03-19 all mallocs/frees replaced w/ pkg_malloc/pkg_free (andrei) - * 2003-04-05: default_uri #define used (jiri) - * 2004-06-06 cleanup: static & auth_db_{init,bind,close.ver} used (andrei) */ #include @@ -113,11 +103,11 @@ int credentials_n; /* Number of credentials in the list */ * Exported functions */ static cmd_export_t cmds[] = { - {"www_authenticate", www_authenticate, 2, authdb_fixup, REQUEST_ROUTE}, - {"www_authorize", www_authenticate, 2, authdb_fixup, REQUEST_ROUTE}, - {"proxy_authenticate", proxy_authenticate, 2, authdb_fixup, REQUEST_ROUTE}, - {"proxy_authorize", proxy_authenticate, 2, authdb_fixup, REQUEST_ROUTE}, - {0, 0, 0, 0, 0} + {"www_authenticate", www_authenticate, 2, authdb_fixup, REQUEST_ROUTE}, + {"www_authorize", www_authenticate, 2, authdb_fixup, REQUEST_ROUTE}, + {"proxy_authenticate", proxy_authenticate, 2, authdb_fixup, REQUEST_ROUTE}, + {"proxy_authorize", proxy_authenticate, 2, authdb_fixup, REQUEST_ROUTE}, + {0, 0, 0, 0, 0} }; @@ -125,19 +115,19 @@ static cmd_export_t cmds[] = { * Exported parameters */ static param_export_t params[] = { - {"db_url", PARAM_STRING, &db_url }, - {"username_column", PARAM_STR, &username_column }, - {"did_column", PARAM_STR, &did_column }, - {"realm_column", PARAM_STR, &realm_column }, - {"password_column", PARAM_STR, &pass_column }, - {"password_column_2", PARAM_STR, &pass_column_2 }, - {"plain_password_column", PARAM_STR, &plain_password_column }, - {"flags_column", PARAM_STR, &flags_column }, - {"calculate_ha1", PARAM_INT, &calc_ha1 }, - {"load_credentials", PARAM_STR, &credentials_list}, - {"use_did", PARAM_INT, &use_did }, - {"check_all_ha1", PARAM_INT, &check_all }, - {0, 0, 0} + {"db_url", PARAM_STRING, &db_url }, + {"username_column", PARAM_STR, &username_column }, + {"did_column", PARAM_STR, &did_column }, + {"realm_column", PARAM_STR, &realm_column }, + {"password_column", PARAM_STR, &pass_column }, + {"password_column_2", PARAM_STR, &pass_column_2 }, + {"plain_password_column", PARAM_STR, &plain_password_column }, + {"flags_column", PARAM_STR, &flags_column }, + {"calculate_ha1", PARAM_INT, &calc_ha1 }, + {"load_credentials", PARAM_STR, &credentials_list}, + {"use_did", PARAM_INT, &use_did }, + {"check_all_ha1", PARAM_INT, &check_all }, + {0, 0, 0} }; @@ -145,15 +135,15 @@ static param_export_t params[] = { * Module interface */ struct module_exports exports = { - "uid_auth_db", - cmds, /* Exported functions */ - 0, /* RPC methods */ - params, /* Exported parameters */ - mod_init, /* module initialization function */ - 0, /* response function */ - destroy, /* destroy function */ - 0, /* oncancel function */ - child_init /* child initialization function */ + "uid_auth_db", + cmds, /* Exported functions */ + 0, /* RPC methods */ + params, /* Exported parameters */ + mod_init, /* module initialization function */ + 0, /* response function */ + destroy, /* destroy function */ + 0, /* oncancel function */ + child_init /* child initialization function */ }; static authdb_table_info_t *registered_tables = NULL; @@ -161,14 +151,14 @@ static authdb_table_info_t *registered_tables = NULL; static int generate_queries(authdb_table_info_t *info) { db_fld_t match_with_did[] = { - { .name = username_column.s, .type = DB_STR }, - { .name = realm_column.s, .type = DB_STR }, - { .name = did_column.s, .type = DB_STR }, + { .name = username_column.s, .type = DB_STR }, + { .name = realm_column.s, .type = DB_STR }, + { .name = did_column.s, .type = DB_STR }, { .name = NULL } }; db_fld_t match_without_did[] = { - { .name = username_column.s, .type = DB_STR }, - { .name = realm_column.s, .type = DB_STR }, + { .name = username_column.s, .type = DB_STR }, + { .name = realm_column.s, .type = DB_STR }, { .name = NULL } }; db_fld_t *result_cols = NULL; @@ -184,7 +174,7 @@ static int generate_queries(authdb_table_info_t *info) result_cols[0].name = pass_column.s; result_cols[0].type = DB_CSTR; - + result_cols[1].name = flags_column.s; result_cols[1].type = DB_INT; for (i = 0; i < credentials_n; i++) { @@ -194,23 +184,23 @@ static int generate_queries(authdb_table_info_t *info) result_cols[2 + i].name = NULL; if (use_did) { - info->query_pass = db_cmd(DB_GET, auth_db_handle, info->table.s, + info->query_pass = db_cmd(DB_GET, auth_db_handle, info->table.s, result_cols, match_with_did, NULL); result_cols[0].name = pass_column_2.s; - info->query_pass2 = db_cmd(DB_GET, auth_db_handle, info->table.s, + info->query_pass2 = db_cmd(DB_GET, auth_db_handle, info->table.s, result_cols, match_with_did, NULL); result_cols[0].name = plain_password_column.s; - info->query_password = db_cmd(DB_GET, auth_db_handle, info->table.s, + info->query_password = db_cmd(DB_GET, auth_db_handle, info->table.s, result_cols, match_with_did, NULL); } else { - info->query_pass = db_cmd(DB_GET, auth_db_handle, info->table.s, + info->query_pass = db_cmd(DB_GET, auth_db_handle, info->table.s, result_cols, match_without_did, NULL); result_cols[0].name = pass_column_2.s; - info->query_pass2 = db_cmd(DB_GET, auth_db_handle, info->table.s, + info->query_pass2 = db_cmd(DB_GET, auth_db_handle, info->table.s, result_cols, match_without_did, NULL); result_cols[0].name = plain_password_column.s; - info->query_password = db_cmd(DB_GET, auth_db_handle, info->table.s, + info->query_password = db_cmd(DB_GET, auth_db_handle, info->table.s, result_cols, match_without_did, NULL); } @@ -235,12 +225,12 @@ static int child_init(int rank) i = registered_tables; while (i) { if (generate_queries(i) < 0) { - ERR("can't prepare queries\n"); + LM_ERR("can't prepare queries\n"); return -1; } i = i->next; } - + return 0; err: @@ -250,56 +240,56 @@ static int child_init(int rank) db_ctx_free(auth_db_handle); } - ERR("Error while initializing database layer\n"); + LM_ERR("Error while initializing database layer\n"); return -1; } static int mod_init(void) { - bind_auth_s_t bind_auth; - - DBG("auth_db module - initializing\n"); - - bind_auth = (bind_auth_s_t)find_export("bind_auth_s", 0, 0); - if (!bind_auth) { - LOG(L_ERR, "auth_db:mod_init: Unable to find bind_auth function\n"); - return -1; - } - if (bind_auth(&auth_api) < 0) { - LOG(L_ERR, "auth_db:child_init: Unable to bind auth module\n"); - return -3; - } - - if (aaa_avps_init(&credentials_list, &credentials, &credentials_n)) { - return -1; - } - - return 0; + bind_auth_s_t bind_auth; + + LM_DBG("auth_db module - initializing\n"); + + bind_auth = (bind_auth_s_t)find_export("bind_auth_s", 0, 0); + if (!bind_auth) { + LM_ERR("Unable to find bind_auth function\n"); + return -1; + } + if (bind_auth(&auth_api) < 0) { + LM_ERR("Unable to bind auth module\n"); + return -3; + } + + if (aaa_avps_init(&credentials_list, &credentials, &credentials_n)) { + return -1; + } + + return 0; } static void destroy(void) { - if (auth_db_handle) { + if (auth_db_handle) { db_ctx_free(auth_db_handle); auth_db_handle = NULL; - } + } } static int str_case_equals(const str *a, const str *b) { /* ugly hack: taken from libcds */ int i; - + if (!a) { if (!b) return 0; else return (b->len == 0) ? 0 : 1; } if (!b) return (a->len == 0) ? 0 : 1; if (a->len != b->len) return 1; - - for (i = 0; i < a->len; i++) + + for (i = 0; i < a->len; i++) if (a->s[i] != b->s[i]) return 1; return 0; } @@ -307,9 +297,9 @@ static int str_case_equals(const str *a, const str *b) static authdb_table_info_t *find_table_info(str *table) { authdb_table_info_t *i = registered_tables; - + /* sequential search is OK because it is called only in child init */ - while (i) { + while (i) { if (str_case_equals(&i->table, table) == 0) return i; i = i->next; } @@ -323,9 +313,10 @@ static authdb_table_info_t *register_table(str *table) info = find_table_info(table); if (info) return info; /* queries for this table already exist */ - info = (authdb_table_info_t*)pkg_malloc(sizeof(authdb_table_info_t) + table->len + 1); + info = (authdb_table_info_t*)pkg_malloc(sizeof(authdb_table_info_t) + + table->len + 1); if (!info) { - ERR("can't allocate pkg mem\n"); + LM_ERR("can't allocate pkg mem\n"); return NULL; } @@ -359,11 +350,12 @@ static int authdb_fixup(void** param, int param_no) return -1; } } else { - ERR("Non-string value of table with credentials is not allowed.\n"); + LM_ERR("Non-string value of table with credentials" + " is not allowed.\n"); /* TODO: allow this too */ return -1; } } - return 0; + return 0; } diff --git a/src/modules/uid_auth_db/uid_auth_db_mod.h b/src/modules/uid_auth_db/uid_auth_db_mod.h index 25ae11e7c91..00dc138d07c 100644 --- a/src/modules/uid_auth_db/uid_auth_db_mod.h +++ b/src/modules/uid_auth_db/uid_auth_db_mod.h @@ -1,6 +1,4 @@ /* - * $Id$ - * * Digest Authentication - Database support * * Copyright (C) 2001-2003 FhG Fokus @@ -22,8 +20,8 @@ * 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 + * 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 */ @@ -45,8 +43,8 @@ extern str did_column; /* 'did' column name */ extern str realm_column; /* 'realm' column name */ extern str pass_column; /* 'password' column name */ extern str pass_column_2; /* Column containing HA1 string constructed - * of user@domain username - */ + * of user@domain username + */ extern str flags_column; /* Flags column in credentials table */ extern int calc_ha1; /* if set to 1, ha1 is calculated by the server */ diff --git a/src/modules/uid_uri_db/uid_uri_db_mod.c b/src/modules/uid_uri_db/uid_uri_db_mod.c index b7bff72e728..e3887fb75d3 100644 --- a/src/modules/uid_uri_db/uid_uri_db_mod.c +++ b/src/modules/uid_uri_db/uid_uri_db_mod.c @@ -395,7 +395,7 @@ static int lookup_user_2(struct sip_msg* msg, char* attr, char* select) while(rec) { if (rec->fld[0].flags & DB_NULL || rec->fld[1].flags & DB_NULL) { - LOG(L_ERR, "lookup_user: Bogus line in %s table\n", uri_table.s); + LM_ERR("bogus line in %s table\n", uri_table.s); goto skip; } diff --git a/src/modules/usrloc/ul_rpc.c b/src/modules/usrloc/ul_rpc.c index bace4885e1c..c27921d0fc7 100644 --- a/src/modules/usrloc/ul_rpc.c +++ b/src/modules/usrloc/ul_rpc.c @@ -31,11 +31,11 @@ /*! CSEQ nr used */ #define RPC_UL_CSEQ 1 /*! call-id used for ul_add and ul_rm_contact */ -static str rpc_ul_cid = str_init("dfjrewr12386fd6-343@kamailio.mi"); +static str rpc_ul_cid = str_init("dfjrewr12386fd6-343@kamailio.rpc"); /*! path used for ul_add and ul_rm_contact */ static str rpc_ul_path = str_init("dummypath"); /*! user agent used for ul_add */ -static str rpc_ul_ua = str_init("SIP Router MI Server"); +static str rpc_ul_ua = str_init(NAME " SIP Router - RPC Server"); extern sruid_t _ul_sruid; @@ -65,10 +65,10 @@ int rpc_dump_contact(rpc_t* rpc, void* ctx, void *ih, ucontact_t* c) return -1; } if (c->expires == 0) { if(rpc->struct_add(vh, "s", "Expires", "permanent")<0) - { + { rpc->fault(ctx, 500, "Internal error adding expire"); return -1; - } + } } else if (c->expires == UL_EXPIRED_TIME) { if(rpc->struct_add(vh, "s", "Expires", "deleted")<0) { @@ -122,19 +122,19 @@ int rpc_dump_contact(rpc_t* rpc, void* ctx, void *ih, ucontact_t* c) return -1; } if(rpc->struct_add(vh, "S", "User-Agent", - (c->user_agent.len)?&c->user_agent: &empty_str)<0) + (c->user_agent.len)?&c->user_agent: &empty_str)<0) { rpc->fault(ctx, 500, "Internal error adding user-agent"); return -1; } if(rpc->struct_add(vh, "S", "Received", - (c->received.len)?&c->received: &empty_str)<0) + (c->received.len)?&c->received: &empty_str)<0) { rpc->fault(ctx, 500, "Internal error adding received"); return -1; } if(rpc->struct_add(vh, "S", "Path", - (c->path.len)?&c->path: &empty_str)<0) + (c->path.len)?&c->path: &empty_str)<0) { rpc->fault(ctx, 500, "Internal error adding path"); return -1; @@ -170,7 +170,7 @@ int rpc_dump_contact(rpc_t* rpc, void* ctx, void *ih, ucontact_t* c) return -1; } if(rpc->struct_add(vh, "S", "Instance", - (c->instance.len)?&c->instance: &empty_str)<0) + (c->instance.len)?&c->instance: &empty_str)<0) { rpc->fault(ctx, 500, "Internal error adding instance"); return -1; @@ -180,17 +180,17 @@ int rpc_dump_contact(rpc_t* rpc, void* ctx, void *ih, ucontact_t* c) rpc->fault(ctx, 500, "Internal error adding reg_id"); return -1; } - if(rpc->struct_add(vh, "d", "Server-Id", c->server_id)<0) + if(rpc->struct_add(vh, "d", "Server-Id", c->server_id)<0) { rpc->fault(ctx, 500, "Internal error adding server_id"); return -1; } - if(rpc->struct_add(vh, "d", "Tcpconn-Id", c->tcpconn_id)<0) + if(rpc->struct_add(vh, "d", "Tcpconn-Id", c->tcpconn_id)<0) { rpc->fault(ctx, 500, "Internal error adding tcpconn_id"); return -1; } - if(rpc->struct_add(vh, "d", "Keepalive", c->keepalive)<0) + if(rpc->struct_add(vh, "d", "Keepalive", c->keepalive)<0) { rpc->fault(ctx, 500, "Internal error adding keepalive"); return -1; @@ -227,7 +227,7 @@ static void ul_rpc_dump(rpc_t* rpc, void* ctx) if(brief.len==5 && (strncmp(brief.s, "brief", 5)==0)) summary = 1; - + for( dl=root ; dl ; dl=dl->next ) { dom = dl->d; if (rpc->add(ctx, "{", &th) < 0) @@ -252,23 +252,23 @@ static void ul_rpc_dump(rpc_t* rpc, void* ctx) if(summary==1) { if(rpc->struct_add(ah, "S", - "AoR", &r->aor)<0) + "AoR", &r->aor)<0) { rpc->fault(ctx, 500, "Internal error creating aor struct"); return; } } else { if(rpc->struct_add(ah, "{", - "Info", &bh)<0) + "Info", &bh)<0) { unlock_ulslot( dom, i); rpc->fault(ctx, 500, "Internal error creating aor struct"); return; } if(rpc->struct_add(bh, "Sd[", - "AoR", &r->aor, - "HashID", r->aorhash, - "Contacts", &ih)<0) + "AoR", &r->aor, + "HashID", r->aorhash, + "Contacts", &ih)<0) { unlock_ulslot( dom, i); rpc->fault(ctx, 500, "Internal error creating aor struct"); @@ -294,8 +294,8 @@ static void ul_rpc_dump(rpc_t* rpc, void* ctx) return; } if(rpc->struct_add(sh, "dd", - "Records", n, - "Max-Slots", max)<0) + "Records", n, + "Max-Slots", max)<0) { rpc->fault(ctx, 500, "Internal error adding stats"); return; @@ -319,7 +319,7 @@ static inline udomain_t* rpc_find_domain(str* table) for( dom=root ; dom ; dom=dom->next ) { if ((dom->name.len == table->len) && - !memcmp(dom->name.s, table->s, table->len)) + !memcmp(dom->name.s, table->s, table->len)) return dom->d; } return 0; @@ -410,8 +410,8 @@ static void ul_rpc_lookup(rpc_t* rpc, void* ctx) return; } if(rpc->struct_add(th, "S[", - "AoR", &aor, - "Contacts", &ih)<0) + "AoR", &aor, + "Contacts", &ih)<0) { unlock_udomain(dom, &aor); rpc->fault(ctx, 500, "Internal error creating aor struct"); @@ -578,7 +578,7 @@ static void ul_rpc_add(rpc_t* rpc, void* ctx) memset( &ci, 0, sizeof(ucontact_info_t)); ret = rpc->scan(ctx, "SSSdfSddd", &table, &aor, &contact, &ci.expires, - &dtemp, &path, &ci.flags, &ci.cflags, &ci.methods); + &dtemp, &path, &ci.flags, &ci.cflags, &ci.methods); if(path.len==1 && (strncmp(path.s, "0", 1)==0)) { LM_DBG("path == 0 -> unset\n"); } @@ -586,8 +586,8 @@ static void ul_rpc_add(rpc_t* rpc, void* ctx) ci.path = &path; } LM_DBG("ret: %d table:%.*s aor:%.*s contact:%.*s expires:%d dtemp:%f path:%.*s flags:%d bflags:%d methods:%d\n", - ret, table.len, table.s, aor.len, aor.s, contact.len, contact.s, - (int) ci.expires, dtemp, (ci.path)?ci.path->len:0, (ci.path && ci.path->s)?ci.path->s:"", ci.flags, ci.cflags, (int) ci.methods); + ret, table.len, table.s, aor.len, aor.s, contact.len, contact.s, + (int) ci.expires, dtemp, (ci.path)?ci.path->len:0, (ci.path && ci.path->s)?ci.path->s:"", ci.flags, ci.cflags, (int) ci.methods); if ( ret != 9) { rpc->fault(ctx, 500, "Not enough parameters or wrong format"); return; @@ -676,52 +676,52 @@ static const char* ul_rpc_add_doc[2] = { static void ul_rpc_db_users(rpc_t* rpc, void* ctx) { - str table = {0, 0}; - char query[QUERY_LEN]; - str query_str; - db1_res_t* res; - int count; - - if (db_mode == NO_DB) { - rpc->fault(ctx, 500, "Command is not supported in db_mode=0"); - return; - } + str table = {0, 0}; + char query[QUERY_LEN]; + str query_str; + db1_res_t* res; + int count; - if (rpc->scan(ctx, "S", &table) != 1) { - rpc->fault(ctx, 500, "Not enough parameters (table to lookup)"); - return; - } + if (db_mode == NO_DB) { + rpc->fault(ctx, 500, "Command is not supported in db_mode=0"); + return; + } - if (user_col.len + domain_col.len + table.len + 32 > QUERY_LEN) { - rpc->fault(ctx, 500, "Too long database query"); - return; - } + if (rpc->scan(ctx, "S", &table) != 1) { + rpc->fault(ctx, 500, "Not enough parameters (table to lookup)"); + return; + } - if (!DB_CAPABILITY(ul_dbf, DB_CAP_RAW_QUERY)) { - rpc->fault(ctx, 500, "Database does not support raw queries"); - return; - } - if (ul_dbf.use_table(ul_dbh, &table) < 0) { - rpc->fault(ctx, 500, "Failed to use table"); - return; - } - - memset(query, 0, QUERY_LEN); - query_str.len = snprintf(query, QUERY_LEN, - "SELECT COUNT(DISTINCT %.*s, %.*s) FROM %.*s WHERE (UNIX_TIMESTAMP(expires) = 0) OR (expires > NOW())", - user_col.len, user_col.s, - domain_col.len, domain_col.s, - table.len, table.s); - query_str.s = query; - if (ul_dbf.raw_query(ul_dbh, &query_str, &res) < 0) { - rpc->fault(ctx, 500, "Failed to query AoR count"); - return; - } + if (user_col.len + domain_col.len + table.len + 32 > QUERY_LEN) { + rpc->fault(ctx, 500, "Too long database query"); + return; + } + + if (!DB_CAPABILITY(ul_dbf, DB_CAP_RAW_QUERY)) { + rpc->fault(ctx, 500, "Database does not support raw queries"); + return; + } + if (ul_dbf.use_table(ul_dbh, &table) < 0) { + rpc->fault(ctx, 500, "Failed to use table"); + return; + } + + memset(query, 0, QUERY_LEN); + query_str.len = snprintf(query, QUERY_LEN, + "SELECT COUNT(DISTINCT %.*s, %.*s) FROM %.*s WHERE (UNIX_TIMESTAMP(expires) = 0) OR (expires > NOW())", + user_col.len, user_col.s, + domain_col.len, domain_col.s, + table.len, table.s); + query_str.s = query; + if (ul_dbf.raw_query(ul_dbh, &query_str, &res) < 0) { + rpc->fault(ctx, 500, "Failed to query AoR count"); + return; + } - count = (int)VAL_INT(ROW_VALUES(RES_ROWS(res))); - ul_dbf.free_result(ul_dbh, res); + count = (int)VAL_INT(ROW_VALUES(RES_ROWS(res))); + ul_dbf.free_result(ul_dbh, res); - rpc->add(ctx, "d", count); + rpc->add(ctx, "d", count); } static const char* ul_rpc_db_users_doc[2] = { @@ -731,49 +731,49 @@ static const char* ul_rpc_db_users_doc[2] = { static void ul_rpc_db_contacts(rpc_t* rpc, void* ctx) { - str table = {0, 0}; - char query[QUERY_LEN]; - str query_str; - db1_res_t* res; - int count; - - if (db_mode == NO_DB) { - rpc->fault(ctx, 500, "Command is not supported in db_mode=0"); - return; - } + str table = {0, 0}; + char query[QUERY_LEN]; + str query_str; + db1_res_t* res; + int count; - if (rpc->scan(ctx, "S", &table) != 1) { - rpc->fault(ctx, 500, "Not enough parameters (table to lookup)"); - return; - } + if (db_mode == NO_DB) { + rpc->fault(ctx, 500, "Command is not supported in db_mode=0"); + return; + } - if (table.len + 22 > QUERY_LEN) { - rpc->fault(ctx, 500, "Too long database query"); - return; - } + if (rpc->scan(ctx, "S", &table) != 1) { + rpc->fault(ctx, 500, "Not enough parameters (table to lookup)"); + return; + } - if (!DB_CAPABILITY(ul_dbf, DB_CAP_RAW_QUERY)) { - rpc->fault(ctx, 500, "Database does not support raw queries"); - return; - } - if (ul_dbf.use_table(ul_dbh, &table) < 0) { - rpc->fault(ctx, 500, "Failed to use table"); - return; - } - - memset(query, 0, QUERY_LEN); - query_str.len = snprintf(query, QUERY_LEN, "SELECT COUNT(*) FROM %.*s WHERE (UNIX_TIMESTAMP(expires) = 0) OR (expires > NOW())", - table.len, table.s); - query_str.s = query; - if (ul_dbf.raw_query(ul_dbh, &query_str, &res) < 0) { - rpc->fault(ctx, 500, "Failed to query contact count"); - return; - } + if (table.len + 22 > QUERY_LEN) { + rpc->fault(ctx, 500, "Too long database query"); + return; + } + + if (!DB_CAPABILITY(ul_dbf, DB_CAP_RAW_QUERY)) { + rpc->fault(ctx, 500, "Database does not support raw queries"); + return; + } + if (ul_dbf.use_table(ul_dbh, &table) < 0) { + rpc->fault(ctx, 500, "Failed to use table"); + return; + } - count = (int)VAL_INT(ROW_VALUES(RES_ROWS(res))); - ul_dbf.free_result(ul_dbh, res); + memset(query, 0, QUERY_LEN); + query_str.len = snprintf(query, QUERY_LEN, "SELECT COUNT(*) FROM %.*s WHERE (UNIX_TIMESTAMP(expires) = 0) OR (expires > NOW())", + table.len, table.s); + query_str.s = query; + if (ul_dbf.raw_query(ul_dbh, &query_str, &res) < 0) { + rpc->fault(ctx, 500, "Failed to query contact count"); + return; + } - rpc->add(ctx, "d", count); + count = (int)VAL_INT(ROW_VALUES(RES_ROWS(res))); + ul_dbf.free_result(ul_dbh, res); + + rpc->add(ctx, "d", count); } static const char* ul_rpc_db_contacts_doc[2] = { @@ -783,49 +783,49 @@ static const char* ul_rpc_db_contacts_doc[2] = { static void ul_rpc_db_expired_contacts(rpc_t* rpc, void* ctx) { - str table = {0, 0}; - char query[QUERY_LEN]; - str query_str; - db1_res_t* res; - int count; - - if (db_mode == NO_DB) { - rpc->fault(ctx, 500, "Command is not supported in db_mode=0"); - return; - } + str table = {0, 0}; + char query[QUERY_LEN]; + str query_str; + db1_res_t* res; + int count; - if (rpc->scan(ctx, "S", &table) != 1) { - rpc->fault(ctx, 500, "Not enough parameters (table to lookup)"); - return; - } + if (db_mode == NO_DB) { + rpc->fault(ctx, 500, "Command is not supported in db_mode=0"); + return; + } - if (table.len + 22 > QUERY_LEN) { - rpc->fault(ctx, 500, "Too long database query"); - return; - } + if (rpc->scan(ctx, "S", &table) != 1) { + rpc->fault(ctx, 500, "Not enough parameters (table to lookup)"); + return; + } - if (!DB_CAPABILITY(ul_dbf, DB_CAP_RAW_QUERY)) { - rpc->fault(ctx, 500, "Database does not support raw queries"); - return; - } - if (ul_dbf.use_table(ul_dbh, &table) < 0) { - rpc->fault(ctx, 500, "Failed to use table"); - return; - } - - memset(query, 0, QUERY_LEN); - query_str.len = snprintf(query, QUERY_LEN, "SELECT COUNT(*) FROM %.*s WHERE (UNIX_TIMESTAMP(expires) > 0) AND (expires <= NOW())", - table.len, table.s); - query_str.s = query; - if (ul_dbf.raw_query(ul_dbh, &query_str, &res) < 0) { - rpc->fault(ctx, 500, "Failed to query contact count"); - return; - } + if (table.len + 22 > QUERY_LEN) { + rpc->fault(ctx, 500, "Too long database query"); + return; + } + + if (!DB_CAPABILITY(ul_dbf, DB_CAP_RAW_QUERY)) { + rpc->fault(ctx, 500, "Database does not support raw queries"); + return; + } + if (ul_dbf.use_table(ul_dbh, &table) < 0) { + rpc->fault(ctx, 500, "Failed to use table"); + return; + } + + memset(query, 0, QUERY_LEN); + query_str.len = snprintf(query, QUERY_LEN, "SELECT COUNT(*) FROM %.*s WHERE (UNIX_TIMESTAMP(expires) > 0) AND (expires <= NOW())", + table.len, table.s); + query_str.s = query; + if (ul_dbf.raw_query(ul_dbh, &query_str, &res) < 0) { + rpc->fault(ctx, 500, "Failed to query contact count"); + return; + } - count = (int)VAL_INT(ROW_VALUES(RES_ROWS(res))); - ul_dbf.free_result(ul_dbh, res); + count = (int)VAL_INT(ROW_VALUES(RES_ROWS(res))); + ul_dbf.free_result(ul_dbh, res); - rpc->add(ctx, "d", count); + rpc->add(ctx, "d", count); } static const char* ul_rpc_db_expired_contacts_doc[2] = {