static inline int insert_siptrace_avp(struct usr_avp *avp, int_str *first_val,db_key_t *keys,db_val_t *vals) { int_str avp_value; if (avp == 0) return 0; if (!is_avp_str_val(avp)) { avp_value.s.s=int2str(first_val->n,&avp_value.s.len); LM_DBG("int val [%.*s]\n",avp_value.s.len,avp_value.s.s); } else { avp_value = *first_val; LM_DBG("str val [%.*s]\n",avp_value.s.len,avp_value.s.s); } db_vals[13].val.str_val.s = avp_value.s.s; db_vals[13].val.str_val.len = avp_value.s.len; LM_DBG("storing info 14...\n"); CON_PS_REFERENCE(db_con) = &siptrace_ps; if (con_set_inslist(&db_funcs,db_con,&ins_list,keys,NR_KEYS) < 0 ) CON_RESET_INSLIST(db_con); if(db_funcs.insert(db_con, keys, vals, NR_KEYS) < 0) { LM_ERR("error storing trace\n"); return -1; } avp = search_next_avp( avp, &avp_value); while(avp!=NULL) { if (!is_avp_str_val(avp)) avp_value.s.s=int2str(avp_value.n,&avp_value.s.len); db_vals[13].val.str_val.s = avp_value.s.s; db_vals[13].val.str_val.len = avp_value.s.len; LM_DBG("### - storing info 14 \n"); CON_PS_REFERENCE(db_con) = &siptrace_ps; if (con_set_inslist(&db_funcs,db_con,&ins_list,keys,NR_KEYS) < 0 ) CON_RESET_INSLIST(db_con); if(db_funcs.insert(db_con, keys, vals, NR_KEYS) < 0) { LM_ERR("error storing trace\n"); return -1; } avp = search_next_avp( avp, &avp_value); } return 0; }
/* * Report originate call setup usage */ void ospReportOrigSetupUsage(void) { osp_dest* dest = NULL; osp_dest* lastused = NULL; struct usr_avp* destavp = NULL; int_str destval; struct search_state state; OSPTTRANHANDLE transaction = -1; int lastcode = 0; int errorcode; LOG(L_DBG, "osp: ospReportOrigSetupUsage\n"); errorcode = OSPPTransactionNew(_osp_provider, &transaction); for (destavp = search_first_avp(AVP_NAME_STR | AVP_VAL_STR, (int_str)OSP_ORIGDEST_NAME, &destval, &state); destavp != NULL; destavp = search_next_avp(&state, &destval)) { /* OSP destination is wrapped in a string */ dest = (osp_dest*)destval.s.s; if (dest->used == 1) { if (dest->reported == 1) { LOG(L_DBG, "osp: orig setup already reported\n"); break; } else { dest->reported = 1; } LOG(L_DBG, "osp: iterating through used destination\n"); ospDumpDestination(dest); lastused = dest; errorcode = ospBuildUsageFromDestination(transaction, dest, lastcode); lastcode = dest->lastcode; } else { LOG(L_DBG, "osp: destination has not been used, breaking out\n"); break; } } if (lastused) { LOG(L_INFO, "osp: report orig setup for call_id '%.*s' transaction_id '%llu'\n", lastused->callidsize, lastused->callid, lastused->transid); errorcode = ospReportUsageFromDestination(transaction, lastused); } else { /* If a Toolkit transaction handle was created, but we did not find * any destinations to report, we need to release the handle. Otherwise, * the ospReportUsageFromDestination will release it. */ OSPPTransactionDelete(transaction); } }
static int attr_equals_xl(struct sip_msg* msg, char* p1, char* format) { avp_ident_t* avpid; avp_value_t avp_val; struct search_state st; str xl_val; avp_t* avp; avpid = &((fparam_t*)p1)->v.avp; if (xl_printstr(msg, (xl_elog_t*) format, &xl_val.s, &xl_val.len) > 0) { for (avp = search_avp(*avpid, &avp_val, &st); avp; avp = search_next_avp(&st, &avp_val)) { if (avp->flags & AVP_VAL_STR) { if ((avp_val.s.len == xl_val.len) && !memcmp(avp_val.s.s, xl_val.s, avp_val.s.len)) return 1; } else { if (avp_val.n == str2s(xl_val.s, xl_val.len, 0)) return 1; } } return -1; } ERR("avp_equals_xl:Error while expanding xl_format\n"); return -1; }
/* * Dump all destination information */ void ospDumpAllDestination(void) { struct usr_avp* destavp = NULL; int_str destval; osp_dest* dest = NULL; int count = 0; for (destavp = search_first_avp(AVP_VAL_STR, _osp_origdest_avpid, NULL, 0); destavp != NULL; destavp = search_next_avp(destavp, NULL)) { get_avp_val(destavp, &destval); /* OSP destination is wrapped in a string */ dest = (osp_dest*)destval.s.s; LM_DBG("....originate '%d'....\n", count++); ospDumpDestination(dest); } if (count == 0) { LM_DBG("there is not originate destination AVP\n"); } if (search_first_avp(AVP_VAL_STR, _osp_termdest_avpid, &destval, 0) != NULL) { /* OSP destination is wrapped in a string */ dest = (osp_dest*)destval.s.s; LM_DBG("....terminate....\n"); ospDumpDestination(dest); } else { LM_DBG("there is not terminate destination AVP\n"); } }
/* * Retrieved the last used originate destination from an AVP * name - OSP_ORIGDEST_NAME * value - osp_dest wrapped in a string * There can be 0, 1 or more destinations. * Find the last used destination (used==1) & supported (support==1), * and return it. * In normal condition, this one is the current destination. But it may * be wrong for loop condition. * return NULL on failure */ osp_dest* ospGetLastOrigDestination(void) { struct usr_avp* destavp = NULL; int_str destval; osp_dest* dest = NULL; osp_dest* lastdest = NULL; struct search_state st; for (destavp = search_first_avp(AVP_NAME_STR | AVP_VAL_STR, (int_str)OSP_ORIGDEST_NAME, NULL, &st); destavp != NULL; destavp = search_next_avp(&st, NULL)) { get_avp_val(destavp, &destval); /* OSP destination is wrapped in a string */ dest = (osp_dest*)destval.s.s; if (dest->used == 1) { if (dest->supported == 1) { lastdest = dest; LM_DBG("curent destination '%s'\n", lastdest->host); } } else { break; } } return lastdest; }
int ds_next_dst(struct sip_msg *msg, int mode) { struct socket_info *sock; struct usr_avp *avp; struct usr_avp *tmp_avp; struct usr_avp *attr_avp; int_str avp_value; int_str sock_avp_value; if(!(ds_flags&DS_FAILOVER_ON) || dst_avp_name < 0) { LM_WARN("failover support disabled\n"); return -1; } tmp_avp = search_first_avp(dst_avp_type, dst_avp_name, NULL, 0); if(tmp_avp==NULL) return -1; /* used avp deleted -- strange */ /* get AVP with next destination URI */ avp = search_next_avp(tmp_avp, &avp_value); destroy_avp(tmp_avp); /* remove old attribute AVP (from prev destination) */ if (attrs_avp_name >= 0) { attr_avp = search_first_avp(attrs_avp_type, attrs_avp_name, NULL, 0); if (attr_avp) destroy_avp(attr_avp); } if(avp==NULL || !(avp->flags&AVP_VAL_STR)) return -1; /* no more avps or value is int */ /* get AVP with next destination socket */ tmp_avp = search_first_avp(sock_avp_type, sock_avp_name, &sock_avp_value, 0); if (tmp_avp) { /* this shuold not happen, it is a bogus state */ sock = NULL; } else { if (sscanf( sock_avp_value.s.s, "%p", (void**)&sock ) != 1) sock = NULL; } if(ds_update_dst(msg, &avp_value.s, sock, mode)!=0) { LM_ERR("cannot set dst addr\n"); return -1; } LM_DBG("using [%.*s]\n", avp_value.s.len, avp_value.s.s); return 1; }
int legs2strar( struct acc_extra *legs, struct sip_msg *rq, str *val_arr, int *int_arr, char *type_arr, int start) { static struct usr_avp *avp[MAX_ACC_LEG]; static struct search_state st[MAX_ACC_LEG]; unsigned short name_type; int_str name; int_str value; int n; int found; int r; found = 0; r = 0; for( n=0 ; legs ; legs=legs->next,n++ ) { /* search for the AVP */ if (start) { if ( pv_get_avp_name( rq, &(legs->spec.pvp), &name, &name_type)<0 ) goto exit; avp[n] = search_first_avp( name_type, name, &value, st + n); } else { avp[n] = search_next_avp(st + n, &value); } /* set new leg record */ if (avp[n]) { found = 1; /* get its value */ if(avp[n]->flags & AVP_VAL_STR) { val_arr[n] = value.s; type_arr[n] = TYPE_STR; } else { val_arr[n].s = int2bstr( value.n, int_buf+r*INT2STR_MAX_LEN, &val_arr[n].len); r++; int_arr[n] = value.n; type_arr[n] = TYPE_INT; } } else { val_arr[n].s = 0; val_arr[n].len = 0; type_arr[n] = TYPE_NULL; } } if (found || start) return n; exit: return 0; }
int _cfgt_get_array_avp_vals(struct sip_msg *msg, pv_param_t *param, srjson_doc_t *jdoc, srjson_t **jobj, str *item_name) { struct usr_avp *avp; unsigned short name_type; int_str avp_name; int_str avp_value; struct search_state state; srjson_t *jobjt; memset(&state, 0, sizeof(struct search_state)); if(pv_get_avp_name(msg, param, &avp_name, &name_type)!=0) { LM_ERR("invalid name\n"); return -1; } *jobj = srjson_CreateArray(jdoc); if(*jobj==NULL) { LM_ERR("cannot create json object\n"); return -1; } if ((avp=search_first_avp(name_type, avp_name, &avp_value, &state))==0) { goto ok; } do { if(avp->flags & AVP_VAL_STR) { jobjt = srjson_CreateStr(jdoc, avp_value.s.s, avp_value.s.len); if(jobjt==NULL) { LM_ERR("cannot create json object\n"); return -1; } } else { jobjt = srjson_CreateNumber(jdoc, avp_value.n); if(jobjt==NULL) { LM_ERR("cannot create json object\n"); return -1; } } srjson_AddItemToArray(jdoc, *jobj, jobjt); } while ((avp=search_next_avp(&state, &avp_value))!=0); ok: item_name->s = avp_name.s.s; item_name->len = avp_name.s.len; return 0; }
static int del_attr(struct sip_msg* msg, char* p1, char* p2) { fparam_t* fp; avp_t* avp; struct search_state st; fp = (fparam_t*)p1; avp = search_avp(fp->v.avp, 0, &st); while (avp) { destroy_avp(avp); avp = search_next_avp(&st, 0); } return 1; }
/* * Writes all avps with name avp_name to new str_list (shm mem) * Be careful: returns NULL pointer if no avp present! * */ struct str_list* get_str_list(unsigned short avp_flags, int_str avp_name) { int_str avp_value; unsigned int len; struct str_list* list_first = 0; struct str_list* list_current = 0 ; struct search_state st; if(!search_first_avp(avp_flags, avp_name, &avp_value, &st)) { return NULL; } do { LM_DBG("AVP found '%.*s'\n", avp_value.s.len, avp_value.s.s); len = sizeof(struct str_list) + avp_value.s.len; if(list_current) { list_current->next = (struct str_list*) shm_malloc( len); list_current=list_current->next; } else { list_current=list_first= (struct str_list*) shm_malloc( len); } if (list_current==0) { LM_ERR("no more shm mem (%d)\n",len); return 0; } memset( list_current, 0, len); list_current->s.s = (char*)( (void*) list_current + sizeof(struct str_list)); list_current->s.len = avp_value.s.len; memcpy(list_current->s.s,avp_value.s.s,avp_value.s.len); } while(search_next_avp(&st, &avp_value)); return list_first; }
/* * Retrieved an unused and supported originate destination from an AVP * name - OSP_ORIGDEST_NAME * value - osp_dest wrapped in a string * There can be 0, 1 or more originate destinations. * Find the 1st unused destination (used==0) & supported (support==1), * return it, and mark it as used (used==1). * return NULL on failure */ osp_dest* ospGetNextOrigDestination(void) { struct usr_avp* destavp = NULL; int_str destval; osp_dest* dest = NULL; osp_dest* result = NULL; struct search_state st; for (destavp = search_first_avp(AVP_NAME_STR | AVP_VAL_STR, (int_str)OSP_ORIGDEST_NAME, NULL, &st); destavp != NULL; destavp = search_next_avp(&st, NULL)) { get_avp_val(destavp, &destval); /* OSP destintaion is wrapped in a string */ dest = (osp_dest*)destval.s.s; if (dest->used == 0) { if (dest->supported == 1) { LM_DBG("orig dest found\n"); dest->used = 1; result = dest; break; } else { /* Make it looks like used */ dest->used = 1; /* 111 means wrong protocol */ dest->lastcode = 111; LM_DBG("destination does not been supported\n"); } } else { LM_DBG("destination has already been used\n"); } } if (result == NULL) { LM_DBG("there is not unused destination\n"); } return result; }
/* * Check if there is an unused and supported originate destination from an AVP * avpid - osp_origdest_avpid * value - osp_dest wrapped in a string * search unused (used==0) & supported (support==1) * return 0 success, -1 failure */ int ospCheckOrigDestination(void) { struct usr_avp* destavp = NULL; int_str destval; osp_dest* dest = NULL; int result = -1; for (destavp = search_first_avp(AVP_VAL_STR, _osp_origdest_avpid, NULL, 0); destavp != NULL; destavp = search_next_avp(destavp, NULL)) { get_avp_val(destavp, &destval); /* OSP destintaion is wrapped in a string */ dest = (osp_dest*)destval.s.s; if (dest->used == 0) { if (dest->supported == 1) { LM_DBG("orig dest exist\n"); result = 0; break; } else { /* Make it looks like used */ dest->used = 1; /* 111 means wrong protocol */ dest->lastcode = 111; LM_DBG("destination does not been supported\n"); } } else { LM_DBG("destination has already been used\n"); } } if (result == -1) { LM_DBG("there is not unused destination\n"); ospReportOrigSetupUsage(); } return result; }
static void remove_avps(avp_t *avp) { struct search_state ss; avp_name_t name; avp_t *a; str *s; if (avp->flags & AVP_NAME_STR) { s = get_avp_name(avp); if (s) name.s = *s; else { name.s.s = NULL; name.s.len = 0; } } else name.n = avp->id; a = search_first_avp(avp->flags, name, 0, &ss); while(a) { destroy_avp(a); a = search_next_avp(&ss, 0); } }
static int xl_get_avp(struct sip_msg *msg, str *res, str *hp, int hi, int hf) { int_str name, val; struct usr_avp *avp, *lavp; struct search_state st; if(msg==NULL || res==NULL || hp==NULL) return -1; name.s=*hp; if (0){ lavp=NULL; for(avp=search_first_avp(AVP_NAME_STR, name, NULL, &st); avp; avp=search_next_avp(&st, NULL)) { lavp=avp; if (hi>0) hi--; else if (hi==0) break; } if (lavp && (hi<=0)) { get_avp_val(lavp, &val); *res=val.s; return 0; } } if ((avp=search_avp_by_index(hf, name, &val, hi))) { if (avp->flags & AVP_VAL_STR) { *res=val.s; } else { res->s=int2str(val.n, &res->len); } return 0; } return xl_get_null(msg, res, hp, hi, hf); }
/* * returns 1 if msg contains an AVP with the given name and value, * returns -1 otherwise */ static int attr_equals(struct sip_msg* msg, char* p1, char* p2) { avp_ident_t avpid; int_str value, avp_value; avp_t* avp; struct search_state st; if (get_avp_id(&avpid, (fparam_t*)p1, msg) < 0) { return -1; } if (p2 && get_str_fparam(&value.s, msg, (fparam_t*)p2) < 0) { ERR("Error while obtaining attribute value from '%s'\n", ((fparam_t*)p2)->orig); return -1; } avp = search_avp(avpid, &avp_value, &st); if (avp == 0) return -1; if (!p2) return 1; while (avp != 0) { if (avp->flags & AVP_VAL_STR) { if ((avp_value.s.len == value.s.len) && !memcmp(avp_value.s.s, value.s.s, avp_value.s.len)) { return 1; } } else { if (avp_value.n == str2s(value.s.s, value.s.len, 0)) { return 1; } } avp = search_next_avp(&st, &avp_value); } return -1; }
/* * Check if there is an unused and supported originate destination from an AVP * name - OSP_ORIGDEST_NAME * value - osp_dest wrapped in a string * search unused (used==0) & supported (support==1) * return 0 success, -1 failure */ int ospCheckOrigDestination(void) { struct usr_avp* destavp = NULL; int_str destval; osp_dest* dest = NULL; int result = -1; struct search_state st; for (destavp = search_first_avp(AVP_NAME_STR | AVP_VAL_STR, (int_str)OSP_ORIGDEST_NAME, NULL, &st); destavp != NULL; destavp = search_next_avp(&st, NULL)) { get_avp_val(destavp, &destval); /* OSP destintaion is wrapped in a string */ dest = (osp_dest*)destval.s.s; if (dest->used == 0) { if (dest->supported == 1) { LM_DBG("orig dest exist\n"); result = 0; break; } else { LM_DBG("destination does not been supported\n"); } } else { LM_DBG("destination has already been used\n"); } } if (result == -1) { LM_DBG("there is not unused destination\n"); } return result; }
static void build_used_uris_list(avp_value_t* used_dests, int* no_dests){ struct search_state st; int_str val; *no_dests = 0; if (!search_first_avp( AVP_VAL_STR | AVP_NAME_STR, cr_uris_avp, &val, &st)) { //LM_DBG("no AVPs - we are done!\n"); return; } used_dests[(*no_dests)++] = val; //LM_DBG(" used_dests[%d]=%.*s \n", (*no_dests)-1, used_dests[(*no_dests)-1].s.len, used_dests[(*no_dests)-1].s.s); while ( search_next_avp(&st, &val) ) { if ( MAX_DESTINATIONS == *no_dests ) { LM_ERR("Too many AVPs - we are done!\n"); return; } used_dests[(*no_dests)++] = val; //LM_DBG(" used_dests[%d]=%.*s \n", (*no_dests)-1, used_dests[(*no_dests)-1].s.len, used_dests[(*no_dests)-1].s.s); } //LM_DBG("successfully built used_uris list!\n"); }
/* * Dump all destination information */ void ospDumpAllDestination(void) { struct usr_avp* destavp = NULL; int_str destval; osp_dest* dest = NULL; int count = 0; struct search_state st; for (destavp = search_first_avp(AVP_NAME_STR | AVP_VAL_STR, (int_str)OSP_ORIGDEST_NAME, NULL, &st); destavp != NULL; destavp = search_next_avp(&st, NULL)) { get_avp_val(destavp, &destval); /* OSP destination is wrapped in a string */ dest = (osp_dest*)destval.s.s; LM_DBG("....originate '%d'....\n", count++); ospDumpDestination(dest); } if (count == 0) { LM_DBG("there is not originate destination AVP\n"); } if (search_first_avp(AVP_NAME_STR | AVP_VAL_STR, (int_str)OSP_TERMDEST_NAME, &destval, 0) != NULL) { /* OSP destination is wrapped in a string */ dest = (osp_dest*)destval.s.s; LM_DBG("....terminate....\n"); ospDumpDestination(dest); } else { LM_DBG("there is not terminate destination AVP\n"); } }
int ops_dbstore_avps (struct sip_msg* msg, struct fis_param *sp, struct db_param *dbp, int use_domain) { struct sip_uri uri; struct usr_avp **avp_list; struct usr_avp *avp; unsigned short name_type; int_str i_s; str uuid; int keys_off; int keys_nr; int n; if (sp->flags&AVPOPS_VAL_NONE) { /* get and parse uri */ if (parse_source_uri( msg, sp->flags, &uri)<0 ) { LOG(L_ERR,"ERROR:avpops:store_avps: failed to get uri\n"); goto error; } /* set values for keys */ keys_off = 1; store_vals[4].val.str_val = (sp->flags&AVPOPS_FLAG_DOMAIN)?empty:uri.user; if (use_domain || sp->flags&AVPOPS_FLAG_DOMAIN) { store_vals[5].val.str_val = uri.host; keys_nr = 5; } else { keys_nr = 4; } } else if (sp->flags&AVPOPS_VAL_AVP) { /* get uuid from avp */ if (get_avp_as_str(sp, &uuid)<0) { LOG(L_ERR,"ERROR:avpops:store_avps: failed to get uuid\n"); goto error; } /* set values for keys */ keys_off = 0; keys_nr = 4; store_vals[0].val.str_val = uuid; } else if (sp->flags&AVPOPS_VAL_STR) { /* use the STR value as uuid */ /* set values for keys */ keys_off = 0; keys_nr = 4; store_vals[0].val.str_val = *sp->val.s; } else { LOG(L_CRIT,"BUG:avpops:store_avps: invalid flag combination (%d)\n", sp->flags); goto error; } /* set uuid/(username and domain) fields */ n =0 ; if ((dbp->a.flags&AVPOPS_VAL_NONE)==0) { /* avp name is known ->set it and its type */ name_type = (((dbp->a.flags&AVPOPS_VAL_INT))?0:AVP_NAME_STR); store_vals[1].val.str_val = dbp->sa; /*attr name*/ avp = search_first_avp( name_type, dbp->a.val, &i_s); for( ; avp; avp=search_next_avp(avp,&i_s)) { /* don't insert avps which were loaded */ if (avp->flags&AVP_IS_IN_DB) continue; /* set type */ store_vals[3].val.int_val = (avp->flags&AVP_NAME_STR?0:AVPOPS_DB_NAME_INT)| (avp->flags&AVP_VAL_STR?0:AVPOPS_DB_VAL_INT); /* set value */ int_str2db_val( i_s, &store_vals[2].val.str_val, avp->flags&AVP_VAL_STR); /* save avp */ if (db_store_avp( store_keys+keys_off, store_vals+keys_off, keys_nr, dbp->table)==0 ) { avp->flags |= AVP_IS_IN_DB; n++; } } } else { /* avp name is unknown -> go through all list */ avp_list = get_avp_list(); avp = *avp_list; for ( ; avp ; avp=avp->next ) { /* don't insert avps which were loaded */ if (avp->flags&AVP_IS_IN_DB) continue; /* check if type match */ if ( !( (dbp->a.flags&(AVPOPS_VAL_INT|AVPOPS_VAL_STR))==0 || ((dbp->a.flags&AVPOPS_VAL_INT)&&((avp->flags&AVP_NAME_STR))==0) ||((dbp->a.flags&AVPOPS_VAL_STR)&&(avp->flags&AVP_NAME_STR)))) continue; /* set attribute name and type */ if ( (i_s.s=get_avp_name(avp))==0 ) i_s.n = avp->id; int_str2db_val( i_s, &store_vals[1].val.str_val, avp->flags&AVP_NAME_STR); store_vals[3].val.int_val = (avp->flags&AVP_NAME_STR?0:AVPOPS_DB_NAME_INT)| (avp->flags&AVP_VAL_STR?0:AVPOPS_DB_VAL_INT); /* set avp value */ get_avp_val( avp, &i_s); int_str2db_val( i_s, &store_vals[2].val.str_val, avp->flags&AVP_VAL_STR); /* save avp */ if (db_store_avp( store_keys+keys_off, store_vals+keys_off, keys_nr, dbp->table)==0) { avp->flags |= AVP_IS_IN_DB; n++; } } } DBG("DEBUG:avpops:store_avps: %d avps were stored\n",n); return n==0?-1:1; error: return -1; }
/* * Report originate call setup usage */ void ospReportOrigSetupUsage(void) { struct usr_avp* destavp = NULL; int_str destval; osp_dest* dest = NULL; osp_dest* lastused = NULL; OSPTTRANHANDLE trans = -1; int lastcode = 0; OSPE_ROLE_STATE rstate; int errcode; errcode = OSPPTransactionNew(_osp_provider, &trans); if (errcode != OSPC_ERR_NO_ERROR) { return; } for (destavp = search_first_avp(AVP_VAL_STR, _osp_origdest_avpid, NULL, 0); destavp != NULL; destavp = search_next_avp(destavp, NULL)) { get_avp_val(destavp, &destval); /* OSP destination is wrapped in a string */ dest = (osp_dest*)destval.s.s; if (dest->used == 1) { LM_DBG("iterating through used destination\n"); if (dest->reported == 1) { LM_DBG("orig setup already reported\n"); break; } else { dest->reported = 1; ospDumpDestination(dest); lastused = dest; if (dest->lastcode == 200) { rstate = OSPC_RSTATE_START; } else if (dest->lastcode == 300) { rstate = OSPC_RSTATE_REDIRECT; } else { rstate = OSPC_RSTATE_STOP; } /* RoleInfo must be set before BuildUsageFromScratch */ OSPPTransactionSetRoleInfo(trans, rstate, OSPC_RFORMAT_OSP, OSPC_RVENDOR_OPENSIPS); ospBuildUsageFromDestination(trans, dest, lastcode); OSPPTransactionSetProtocol(trans, OSPC_PROTTYPE_SOURCE, OSPC_PROTNAME_SIP); OSPPTransactionSetProtocol(trans, OSPC_PROTTYPE_DESTINATION, dest->protocol); lastcode = dest->lastcode; } } else { LM_DBG("destination has not been used, breaking out\n"); break; } } if (lastused) { LM_INFO("report orig setup for call_id '%.*s' transaction_id '%llu'\n", lastused->callidsize, lastused->callid, lastused->transid); ospReportUsageFromDestination(trans, lastused); } else { /* If a Toolkit transaction handle was created, but we did not find * any destinations to report, we need to release the handle. Otherwise, * the ospReportUsageFromDestination will release it. */ OSPPTransactionDelete(trans); } }
int do_lb_reset(struct sip_msg *req, struct lb_data *data) { struct usr_avp *id_avp; struct usr_avp *res_avp, *del_res_avp; int_str id_val; int_str res_val; struct dlg_cell *dlg; struct lb_dst *it_d, *last_dst; struct lb_resource *it_r; if ( (dlg=lb_dlg_binds.get_dlg())==NULL ) { LM_ERR("no dialog found for this call, LB not started\n"); return -1; } /* remove any saved AVPs */ destroy_avps(0, group_avp_name, 0); destroy_avps(0, flags_avp_name, 0); destroy_avps(0, mask_avp_name, 0); /* get previous iteration destination, if any */ last_dst = NULL; id_avp = search_first_avp(0, id_avp_name, &id_val, NULL); if( id_avp && (is_avp_str_val(id_avp) == 0) ) { for( it_d=data->dsts ; it_d ; it_d=it_d->next ) { if( it_d->id == id_val.n ) { last_dst = it_d; LM_DBG("reset LB - found previous dst %d [%.*s]\n", last_dst->id, last_dst->profile_id.len, last_dst->profile_id.s); break; } } } destroy_avps(0, id_avp_name, 0); /* any valid previous iteration ? */ if(last_dst == NULL) { /* simply delete all possible resources */ destroy_avps(0, res_avp_name, 1); } else { /* search and clean up previous iteration resources, if any */ res_avp = search_first_avp(0, res_avp_name, &res_val, NULL); while (res_avp) { if ( (it_r=get_resource_by_name( data, &res_val.s))!=NULL ) { if( lb_dlg_binds.unset_profile(dlg, &last_dst->profile_id, it_r->profile) != 1 ) LM_ERR("reset LB - failed to remove from profile [%.*s]->" "[%.*s]\n", res_val.s.len, res_val.s.s, last_dst->profile_id.len, last_dst->profile_id.s ); } else { LM_WARN("reset LB - ignore unknown previous resource " "[%.*s]\n", res_val.s.len, res_val.s.s); } del_res_avp = res_avp; res_avp = search_next_avp(del_res_avp, &res_val); destroy_avp(del_res_avp); } } return 0; }
int lb_route(struct sip_msg *req, int group, struct lb_res_str_list *rl, unsigned int flags, struct lb_data *data, int reuse) { /* resources for previous iteration */ static struct lb_resource **res_prev = NULL; static unsigned int res_prev_size = 0; /* resources for new iteration */ static struct lb_resource **res_new = NULL; static unsigned int res_new_size = 0; /* probed destinations bitmap */ static unsigned int *dst_bitmap = NULL; static unsigned int bitmap_size = 0; /* selected destinations buffer */ static struct lb_dst **dsts = NULL; static unsigned int dsts_size = 0; /* control vars */ struct lb_resource **res_cur; int res_prev_n, res_new_n, res_cur_n; struct lb_dst **dsts_cur; struct lb_dst *last_dst, *dst; unsigned int dsts_size_cur, dsts_size_max; unsigned int *dst_bitmap_cur; unsigned int bitmap_size_cur; struct dlg_cell *dlg; /* AVP related vars */ struct usr_avp *group_avp; struct usr_avp *flags_avp; struct usr_avp *mask_avp; struct usr_avp *id_avp; struct usr_avp *res_avp; int_str group_val; int_str flags_val; int_str mask_val; int_str id_val; int_str res_val; /* iterators, e.t.c. */ struct lb_dst *it_d; struct lb_resource *it_r; int load, it_l; int i, j, cond; /* init control vars state */ res_cur = NULL; res_cur_n = res_prev_n = res_new_n = 0; last_dst = dst = NULL; dst_bitmap_cur = NULL; /* search and fill new resources references if we should not reuse previous iteration data */ if( !reuse ) { res_new_n = rl->n; /* adjust size of statically allocated buffer */ if( res_new_n > res_new_size ) { res_new = (struct lb_resource **)pkg_realloc (res_new, (res_new_n * sizeof(struct lb_resource *))); if( res_new == NULL ) { res_new_size = 0; LM_ERR("no more pkg mem - resources ptr buffer realloc " "failure\n"); return -1; } res_new_size = res_new_n; } /* fill resource references */ for( it_r=data->resources,i=0 ; it_r ; it_r=it_r->next ) { if( search_resource_str(rl, &it_r->name) ) { res_new[i++] = it_r; LM_DBG("initial call of LB - found requested %d/%d " "resource [%.*s]\n", i, res_new_n, it_r->name.len, it_r->name.s); } } if( i != res_new_n ) { LM_ERR("initial call of LB - unknown resource found in " "input string\n"); return -1; } /* set 'res_new' as current iteration buffer */ res_cur = res_new; res_cur_n = res_new_n; } /* always search for previous iteration data, no matter if we will reuse it or not */ group_avp = search_first_avp(0, group_avp_name, &group_val, NULL); flags_avp = search_first_avp(0, flags_avp_name, &flags_val, NULL); mask_avp = search_first_avp(0, mask_avp_name, &mask_val, NULL); id_avp = search_first_avp(0, id_avp_name, &id_val, NULL); /* sanity checks for fetched AVPs */ if( group_avp && !(is_avp_str_val(group_avp) == 0) ) { destroy_avp(group_avp); group_avp = NULL; } if( flags_avp && !(is_avp_str_val(flags_avp) == 0) ) { destroy_avp(flags_avp); flags_avp = NULL; } if( mask_avp && !(is_avp_str_val(mask_avp) != 0) ) { destroy_avp(mask_avp); mask_avp = NULL; } if( id_avp && !(is_avp_str_val(id_avp) == 0) ) { destroy_avp(id_avp); id_avp = NULL; } /* get previous iteration destination, if any */ if( id_avp ) { for( it_d=data->dsts ; it_d ; it_d=it_d->next ) { if( it_d->id == id_val.n ) { last_dst = it_d; LM_DBG("%s call of LB - found previous dst %d [%.*s]\n", (reuse ? "sequential" : "initial"), last_dst->id, last_dst->profile_id.len, last_dst->profile_id.s); break; } } } /* search and fill previous iteration resources references only if... */ if( /* we should reuse previous resources list */ reuse || /* we have 'last_dst', i.e. previous iteration was successfull and * we need to clean it up */ (last_dst != NULL) ) { do { cond = 0; /* use it here as a 'start loop again' flag */ res_prev_n = 0; res_avp = search_first_avp(0, res_avp_name, &res_val, NULL); for( ; res_avp ; res_avp=search_next_avp(res_avp, &res_val) ) { /* ignore AVPs with invalid type */ if( !(is_avp_str_val(res_avp) != 0) ) continue; if ( (it_r=get_resource_by_name( data, &res_val.s))==NULL ) { LM_WARN("%s call of LB - ignore unknown previous " "resource [%.*s]\n", (reuse?"sequential":"initial"), res_val.s.len, res_val.s.s); continue; } /* fill buffer only if buffer size not exeeded */ if( res_prev_n < res_prev_size ) { res_prev[res_prev_n] = it_r; LM_DBG("%s call of LB - found previous resource [%.*s]\n", (reuse ? "sequential" : "initial"), it_r->name.len, it_r->name.s); } res_prev_n++; } /* adjust size of statically allocated buffer */ if( res_prev_n > res_prev_size ) { /* small hack: if we need to adjust 'res_prev' buffer adjust * it according to 'res_new' size to minimize * future pkg_realloc()'s */ if( !reuse && (res_prev_n < res_new_n) ) res_prev_n = res_new_n; res_prev = (struct lb_resource **)pkg_realloc (res_prev, (res_prev_n * sizeof(struct lb_resource *))); if( res_prev == NULL ) { res_prev_size = 0; LM_ERR("no more pkg mem - previous resources ptr " "buffer realloc failure\n"); return -1; } res_prev_size = res_prev_n; cond = 1; } } while( cond ); } /* reuse previous iteration resources, group and flags */ if( reuse ) { /* set 'res_prev' as current iteration buffer */ res_cur = res_prev; res_cur_n = res_prev_n; if( res_cur_n == 0 ) { LM_ERR("sequential call of LB - cannot find previous resources\n"); return -1; } if( group_avp ) group = group_val.n; else { LM_ERR("sequential call of LB - cannot find previous group\n"); return -1; } if( flags_avp ) flags = flags_val.n; else flags = LB_FLAGS_DEFAULT; LM_DBG("sequential call of LB - found previous group %d and " "flags 0x%x\n", group, flags); } /* sanity check - double check that we have a resource list to work with */ if( (res_cur == NULL) || (res_cur_n == 0) ) { LM_ERR("%s call of LB - no resources list to work with\n", (reuse ? "sequential" : "initial")); return -1; } /* [re-]initialize/reuse destinations mask */ /* sanity check - always calculate current iteration * res_cur[]->bitmap_size */ bitmap_size_cur=(unsigned int)(-1); for( i=0 ; i<res_cur_n ; i++ ) { if( bitmap_size_cur > res_cur[i]->bitmap_size ) bitmap_size_cur = res_cur[i]->bitmap_size; } /* always try to reuse 'mask' buffer from AVP, even if we need * to reinitialize it to avoid un-neded AVP ops */ if(mask_avp && (mask_val.s.len==(bitmap_size_cur*sizeof(unsigned int)))) { dst_bitmap_cur = (unsigned int *)mask_val.s.s; } /* ...or use our static buffer */ if( dst_bitmap_cur == NULL ) { /* adjust size of statically allocated buffer */ if( bitmap_size_cur > bitmap_size ) { dst_bitmap = (unsigned int *)pkg_realloc (dst_bitmap, (bitmap_size_cur * sizeof(unsigned int))); if( dst_bitmap == NULL ) { bitmap_size = 0; LM_ERR("no more pkg mem - dst bitmap buffer realloc failed\n"); return -1; } bitmap_size = bitmap_size_cur; } dst_bitmap_cur = dst_bitmap; } /* reinitalize buffer if... */ if( (dst_bitmap_cur == dst_bitmap) || /* it is our static buffer */ !reuse /* should not reuse previous iteration data */ ) { if( reuse ) { LM_WARN("sequential call of LB - cannot %s previous mask, routing " "will be re-started", (mask_avp ? "reuse" : "find")); } memset(dst_bitmap_cur, 0xff, (bitmap_size_cur * sizeof(unsigned int))); for( i=0 ; i<res_cur_n ; i++ ) { for( j=0 ; j<bitmap_size_cur ; j++ ) dst_bitmap_cur[j] &= res_cur[i]->dst_bitmap[j]; } } /* init selected destinations buff */ dsts_cur = NULL; dsts_size_max = (flags & LB_FLAGS_RANDOM) ? data->dst_no : 1; if( dsts_size_max > 1 ) { if( dsts_size_max > dsts_size ) { dsts = (struct lb_dst **)pkg_realloc (dsts, (dsts_size_max * sizeof(struct lb_dst *))); if( dsts == NULL ) { dsts_size_max = dsts_size = 0; LM_WARN("no more pkg mem - dsts buffer realloc failed\n"); } else dsts_size = dsts_size_max; } dsts_cur = dsts; } if( dsts_cur == NULL ) { /* fallback to no-buffer / 'select first' scenario */ dsts_cur = &dst; dsts_size_max = 1; } /* be sure the dialog is created */ if ( (dlg=lb_dlg_binds.get_dlg())==NULL ) { if( lb_dlg_binds.create_dlg(req, 0) != 1 ) { LM_ERR("%s call of LB - failed to create dialog\n", (reuse ? "sequential" : "initial")); return -1; } /* get the dialog reference */ dlg = lb_dlg_binds.get_dlg(); } /* we're initialized from here and no errors could abort us */ /* remove the dialog from previous profiles, if any */ if ( (last_dst != NULL) && (res_prev_n > 0) ) { for( i=0 ; i<res_prev_n ; i++ ) { if( lb_dlg_binds.unset_profile(dlg, &last_dst->profile_id, res_prev[i]->profile) != 1 ) LM_ERR("%s call of LB - failed to remove from profile [%.*s]" "->[%.*s]\n", (reuse ? "sequential" : "initial"), res_prev[i]->profile->name.len, res_prev[i]->profile->name.s, last_dst->profile_id.len, last_dst->profile_id.s ); } } /* lock resources */ for( i=0 ; i<res_cur_n ; i++ ) lock_get(res_cur[i]->lock); /* do the load-balancing */ /* select destinations */ cond = 0; /* use it here as a 'first iteration' flag */ load = it_l = 0; dsts_size_cur = 0; for( it_d=data->dsts,i=0,j=0 ; it_d ; it_d=it_d->next ) { if( it_d->group == group ) { if( (dst_bitmap_cur[i] & (1 << j)) && ((it_d->flags & LB_DST_STAT_DSBL_FLAG) == 0) ) { /* valid destination (group & resources & status) */ if( get_dst_load(res_cur, res_cur_n, it_d, flags, &it_l) ) { /* only valid load here */ if( (it_l > 0) || (flags & LB_FLAGS_NEGATIVE) ) { /* only allowed load here */ if( !cond/*first pass*/ || (it_l > load)/*new max*/ ) { cond = 1; /* restart buffer */ dsts_size_cur = 0; } else if( it_l < load ) { /* lower availability -> new iteration */ continue; } /* add destination to to selected destinations buffer, * if we have a room for it */ if( dsts_size_cur < dsts_size_max ) { load = it_l; dsts_cur[dsts_size_cur++] = it_d; LM_DBG("%s call of LB - destination %d <%.*s> " "selected for LB set with free=%d\n", (reuse ? "sequential" : "initial"), it_d->id, it_d->uri.len, it_d->uri.s, it_l ); } } } else { LM_WARN("%s call of LB - skipping destination %d <%.*s> - " "unable to calculate free resources\n", (reuse ? "sequential" : "initial"), it_d->id, it_d->uri.len, it_d->uri.s ); } } else { LM_DBG("%s call of LB - skipping destination %d <%.*s> " "(filtered=%d , disabled=%d)\n", (reuse ? "sequential" : "initial"), it_d->id, it_d->uri.len, it_d->uri.s, ((dst_bitmap_cur[i] & (1 << j)) ? 0 : 1), ((it_d->flags & LB_DST_STAT_DSBL_FLAG) ? 1 : 0) ); } } if( ++j == (8 * sizeof(unsigned int)) ) { i++; j=0; } } /* choose one destination among selected */ if( dsts_size_cur > 0 ) { if( (dsts_size_cur > 1) && (flags & LB_FLAGS_RANDOM) ) { dst = dsts_cur[rand() % dsts_size_cur]; } else { dst = dsts_cur[0]; } } if( dst != NULL ) { LM_DBG("%s call of LB - winning destination %d <%.*s> selected " "for LB set with free=%d\n", (reuse ? "sequential" : "initial"), dst->id, dst->uri.len, dst->uri.s, load ); /* add to the profiles */ for( i=0 ; i<res_cur_n ; i++ ) { if( lb_dlg_binds.set_profile(dlg, &dst->profile_id, res_cur[i]->profile, 0) != 0 ) LM_ERR("%s call of LB - failed to add to profile [%.*s]->" "[%.*s]\n", (reuse ? "sequential" : "initial"), res_cur[i]->profile->name.len, res_cur[i]->profile->name.s, dst->profile_id.len, dst->profile_id.s); } /* set dst as used (not selected) */ for( it_d=data->dsts,i=0,j=0 ; it_d ; it_d=it_d->next ) { if( it_d == dst ) { dst_bitmap_cur[i] &= ~(1 << j); break; } if( ++j == (8 * sizeof(unsigned int)) ) { i++; j=0; } } } else { LM_DBG("%s call of LB - no destination found\n", (reuse ? "sequential" : "initial")); } /* unlock resources */ for( i=0 ; i<res_cur_n ; i++ ) lock_release(res_cur[i]->lock); /* we're done with load-balancing, now save state */ /* save state - group */ if( group_avp == NULL ) { group_val.n = group; if( add_avp(0, group_avp_name, group_val) != 0 ) { LM_ERR("failed to add GROUP AVP\n"); } } else if( group_val.n != group ) { group_avp->data = (void *)(long)group; } /* save state - flags, save only if they are set */ if( flags_avp == NULL ) { if( flags != LB_FLAGS_DEFAULT ) { flags_val.n = flags; if( add_avp(0, flags_avp_name, flags_val) != 0 ) { LM_ERR("failed to add FLAGS AVP\n"); } } } else if( flags_val.n != flags ) { flags_avp->data = (void *)(long)flags; } /* save state - dst_bitmap mask */ if( (mask_avp!=NULL) && (dst_bitmap_cur!=(unsigned int *)mask_val.s.s) ) { destroy_avp(mask_avp); mask_avp = NULL; } if( mask_avp == NULL ) { mask_val.s.s = (char *)dst_bitmap_cur; mask_val.s.len = bitmap_size_cur * sizeof(unsigned int); if( add_avp(AVP_VAL_STR, mask_avp_name, mask_val) != 0 ) { LM_ERR("failed to add MASK AVP\n"); } } /* save state - dst, save only if we have one */ if( id_avp == NULL ) { if( dst != NULL ) { id_val.n = dst->id; if( add_avp(0, id_avp_name, id_val) != 0 ) { LM_ERR("failed to add ID AVP\n"); } } } else { if( dst != NULL ) { id_avp->data = (void *)(long)dst->id; } else { destroy_avp(id_avp); id_avp = NULL; } } /* save state - res */ /* iterate AVPs once and delete old resources */ destroy_avps(0, res_avp_name, 1 /*all*/); /* add new resources */ for( i=0 ; i<res_cur_n ; i++ ) { res_val.s = res_cur[i]->name; if( add_avp(AVP_VAL_STR, res_avp_name, res_val) != 0 ) LM_ERR("failed to add RES AVP\n"); } /* outcome: set dst uri */ if( (dst != NULL) && (set_dst_uri(req, &dst->uri) != 0) ) { LM_ERR("failed to set duri\n"); return -2; } return dst ? 0 : -2; }
/* * Request OSP authorization and routeing * param msg SIP message * param ignore1 * param ignore2 * return MODULE_RETURNCODE_TRUE success, MODULE_RETURNCODE_FALSE failure, others error */ int ospRequestRouting( struct sip_msg* msg, char* ignore1, char* ignore2) { int i, errcode; char rn[OSP_STRBUF_SIZE]; char cic[OSP_STRBUF_SIZE]; int npdi; OSPE_OPERATOR_NAME type; char opname[OSPC_OPNAME_NUMBER][OSP_STRBUF_SIZE]; osp_inbound inbound; char sourcebuf[OSP_STRBUF_SIZE]; char srcdevbuf[OSP_STRBUF_SIZE]; char divhostbuf[OSP_STRBUF_SIZE]; char useragent[OSP_STRBUF_SIZE]; struct usr_avp* avp = NULL; int_str avpval; unsigned int cinfonum = 0; char cinfo[OSP_DEF_CINFONUM][OSP_STRBUF_SIZE]; char cinfostr[OSP_STRBUF_SIZE]; unsigned int callidnumber = 1; OSPT_CALL_ID* callids[callidnumber]; unsigned int logsize = 0; char* detaillog = NULL; char tohost[OSP_STRBUF_SIZE]; char tohostbuf[OSP_STRBUF_SIZE]; const char* preferred[2] = { NULL }; unsigned int destcount; struct timeval ts, te, td; char datebuf[OSP_STRBUF_SIZE]; unsigned int sdpfpnum = 0; char sdpfp[OSP_DEF_SDPFPNUM][OSP_STRBUF_SIZE]; char* sdpfpstr[OSP_DEF_SDPFPNUM]; OSPTTRANHANDLE trans = -1; int result = MODULE_RETURNCODE_FALSE; ospInitInboundInfo(&inbound); if ((errcode = OSPPTransactionNew(_osp_provider, &trans)) != OSPC_ERR_NO_ERROR) { LM_ERR("failed to create new OSP transaction (%d)\n", errcode); } else if (ospGetCallId(msg, &(callids[0])) != 0) { LM_ERR("failed to extract call id\n"); } else if (ospGetFromUser(msg, inbound.calling, sizeof(inbound.calling)) != 0) { LM_ERR("failed to extract calling number\n"); } else if ((ospGetUriUser(msg, inbound.called, sizeof(inbound.called)) != 0) && (ospGetToUser(msg, inbound.called, sizeof(inbound.called)) != 0)) { LM_ERR("failed to extract called number\n"); } else if (ospGetSource(msg, inbound.source, sizeof(inbound.source)) != 0) { LM_ERR("failed to extract source address\n"); } else if (ospGetSrcDev(msg, inbound.srcdev, sizeof(inbound.srcdev)) != 0) { LM_ERR("failed to extract source deivce address\n"); } else { inbound.authtime = time(NULL); if(msg->rcv.bind_address && msg->rcv.bind_address->address_str.s) { ospCopyStrToBuffer(&msg->rcv.bind_address->address_str, inbound.ingressaddr, sizeof(inbound.ingressaddr)); } ospConvertToOutAddress(inbound.source, sourcebuf, sizeof(sourcebuf)); ospConvertToOutAddress(inbound.srcdev, srcdevbuf, sizeof(srcdevbuf)); switch (_osp_service_type) { case 1: case 2: OSPPTransactionSetServiceType(trans, (_osp_service_type == 1) ? OSPC_SERVICE_NPQUERY : OSPC_SERVICE_CNAMQUERY); ospGetToHost(msg, tohost, sizeof(tohost)); ospConvertToOutAddress(tohost, tohostbuf, sizeof(tohostbuf)); preferred[0] = tohostbuf; destcount = 1; break; case 0: default: OSPPTransactionSetServiceType(trans, OSPC_SERVICE_VOICE); destcount = _osp_max_dests; break; } if (ospGetNpParam(msg, rn, sizeof(rn), cic, sizeof(cic), &npdi) == 0) { OSPPTransactionSetNumberPortability(trans, rn, cic, npdi); } for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) { if (ospGetOperatorName(msg, type, opname[type], sizeof(opname[type])) == 0) { OSPPTransactionSetOperatorName(trans, type, opname[type]); } } if (ospGetFromDisplay(msg, inbound.fromdisplay, sizeof(inbound.fromdisplay)) == 0) { OSPPTransactionSetFrom(trans, OSPC_NFORMAT_DISPLAYNAME, inbound.fromdisplay); } if (ospGetFromUri(msg, inbound.fromuri, sizeof(inbound.fromuri)) == 0) { OSPPTransactionSetFrom(trans, OSPC_NFORMAT_URL, inbound.fromuri); } if (ospGetToUri(msg, inbound.touri, sizeof(inbound.touri)) == 0) { OSPPTransactionSetTo(trans, OSPC_NFORMAT_URL, inbound.touri); } if (ospGetPaiUser(msg, inbound.paiuser, sizeof(inbound.paiuser)) == 0) { OSPPTransactionSetAssertedId(trans, OSPC_NFORMAT_E164, inbound.paiuser); } if (ospGetRpidUser(msg, inbound.rpiduser, sizeof(inbound.rpiduser)) == 0) { OSPPTransactionSetRemotePartyId(trans, OSPC_NFORMAT_E164, inbound.rpiduser); } if (ospGetPciUser(msg, inbound.pciuser, sizeof(inbound.pciuser)) == 0) { OSPPTransactionSetChargeInfo(trans, OSPC_NFORMAT_E164, inbound.pciuser); } if (ospGetDiversion(msg, inbound.divuser, sizeof(inbound.divuser), inbound.divhost, sizeof(inbound.divhost)) == 0) { ospConvertToOutAddress(inbound.divhost, divhostbuf, sizeof(divhostbuf)); } else { divhostbuf[0] = '\0'; } OSPPTransactionSetDiversion(trans, inbound.divuser, divhostbuf); if (ospGetUserAgent(msg, useragent, sizeof(useragent)) == 0) { OSPPTransactionSetUserAgent(trans, useragent); } OSPPTransactionSetProtocol(trans, OSPC_PROTTYPE_SOURCE, OSPC_PROTNAME_SIP); if (ospGetAVP(_osp_snid_avpid, _osp_snid_avptype, inbound.snid, sizeof(inbound.snid)) == 0) { OSPPTransactionSetNetworkIds(trans, inbound.snid, ""); } else { inbound.snid[0] = '\0'; } if (_osp_cinfo_avpid >= 0) { for (i = 0, avp = search_first_avp(_osp_cinfo_avptype, _osp_cinfo_avpid, NULL, 0); ((i < OSP_DEF_CINFONUM) && (avp != NULL)); i++, avp = search_next_avp(avp, NULL)) { get_avp_val(avp, &avpval); if ((avp->flags & AVP_VAL_STR) && (avpval.s.s && avpval.s.len)) { snprintf(cinfo[i], sizeof(cinfo[i]), "%.*s", avpval.s.len, avpval.s.s); } else { cinfo[i][0] = '\0'; } } cinfonum = i; cinfostr[0] = '\0'; for (i = 0; i < cinfonum; i++) { if (cinfo[cinfonum - i - 1][0] != '\0') { OSPPTransactionSetCustomInfo(trans, i, cinfo[cinfonum - i - 1]); snprintf(cinfostr + strlen(cinfostr), sizeof(cinfostr) - strlen(cinfostr), "custom_info%d '%s' ", i + 1, cinfo[cinfonum - i - 1]); } } } if (ospGetAVP(_osp_srcmedia_avpid, _osp_srcmedia_avptype, inbound.srcmedia, sizeof(inbound.srcmedia)) == 0) { OSPPTransactionSetSrcAudioAddr(trans, inbound.srcmedia); } else { inbound.srcmedia[0] = '\0'; } inbound.date = 0; if (ospGetAVP(_osp_reqdate_avpid, _osp_reqdate_avptype, datebuf, sizeof(datebuf)) == 0) { if (ospStrToTime(datebuf, &inbound.date) == 0) { OSPPTransactionSetRequestDate(trans, inbound.date); } } if (_osp_sdpfp_avpid >= 0) { for (i = 0, avp = search_first_avp(_osp_sdpfp_avptype, _osp_sdpfp_avpid, NULL, 0); ((i < OSP_DEF_SDPFPNUM) && (avp != NULL)); i++, avp = search_next_avp(avp, NULL)) { get_avp_val(avp, &avpval); if ((avp->flags & AVP_VAL_STR) && (avpval.s.s && avpval.s.len)) { snprintf(sdpfp[i], sizeof(sdpfp[i]), "%.*s", avpval.s.len, avpval.s.s); } else { sdpfp[i][0] = '\0'; } } sdpfpnum = i; for (i = 0; i < sdpfpnum; i++) { sdpfpstr[i] = sdpfp[sdpfpnum - i - 1]; } OSPPTransactionSetFingerPrint(trans, sdpfpnum, (const char**)sdpfpstr); } ospReportIdentity(trans); LM_INFO("request auth and routing for: " "service '%d' " "source '%s' " "srcdev '%s' " "snid '%s' " "calling '%s' " "called '%s' " "preferred '%s' " "nprn '%s' " "npcic '%s' " "npdi '%d' " /* "spid '%s' " "ocn '%s' " "spn '%s' " "altspn '%s' " "mcc '%s' " "mnc '%s' " */ "fromdisplay '%s' " "paiuser '%s' " "rpiduser '%s' " "pciuser '%s' " "divuser '%s' " "divhost '%s' " "srcmedia '%s' " "callid '%.*s' " "destcount '%d' " "%s\n", _osp_service_type, sourcebuf, srcdevbuf, inbound.snid, inbound.calling, inbound.called, (preferred[0] == NULL) ? "" : preferred[0], rn, cic, npdi, /* opname[OSPC_OPNAME_SPID], opname[OSPC_OPNAME_OCN], opname[OSPC_OPNAME_SPN], opname[OSPC_OPNAME_ALTSPN], opname[OSPC_OPNAME_MCC], opname[OSPC_OPNAME_MNC], */ inbound.fromdisplay, inbound.paiuser, inbound.rpiduser, inbound.pciuser, inbound.divuser, divhostbuf, inbound.srcmedia, callids[0]->Length, callids[0]->Value, destcount, cinfostr); gettimeofday(&ts, NULL); /* try to request authorization */ errcode = OSPPTransactionRequestAuthorisation( trans, /* transaction handle */ sourcebuf, /* from the configuration file */ srcdevbuf, /* source device of call, protocol specific, in OSP format */ inbound.calling, /* calling number in nodotted e164 notation */ OSPC_NFORMAT_E164, /* calling number format */ inbound.called, /* called number */ OSPC_NFORMAT_E164, /* called number format */ "", /* optional username string, used if no number */ callidnumber, /* number of call ids, here always 1 */ callids, /* sized-1 array of call ids */ preferred, /* preferred destinations */ &destcount, /* max destinations, after call dest_count */ &logsize, /* size allocated for detaillog (next param) 0=no log */ detaillog); /* memory location for detaillog to be stored */ gettimeofday(&te, NULL); timersub(&te, &ts, &td); LM_INFO("authreq cost = %lu.%06lu for call-id '%.*s'\n", td.tv_sec, td.tv_usec, callids[0]->Length, callids[0]->Value); if ((errcode == OSPC_ERR_NO_ERROR) && (ospLoadRoutes(trans, destcount, &inbound) == 0)) { LM_INFO("there are '%d' OSP routes, call_id '%.*s'\n", destcount, callids[0]->Length, callids[0]->Value); result = MODULE_RETURNCODE_TRUE; } else { LM_ERR("failed to request auth and routing (%d), call_id '%.*s'\n", errcode, callids[0]->Length, callids[0]->Value); switch (errcode) { case OSPC_ERR_HTTP_BAD_REQUEST: result = -4000; break; case OSPC_ERR_TRAN_BAD_REQUEST: result = -4001; break; case OSPC_ERR_HTTP_UNAUTHORIZED: result = -4010; break; case OSPC_ERR_TRAN_UNAUTHORIZED: result = -4011; break; case OSPC_ERR_TRAN_ROUTE_BLOCKED: result = -4030; break; case OSPC_ERR_TRAN_ROUTE_NOT_FOUND: result = -4040; break; case OSPC_ERR_TRAN_MAY_NOT_ORIGINATE: result = -4050; break; case OSPC_ERR_TRAN_CALLING_INVALID: result = -4280; break; case OSPC_ERR_SOCK_CONNECT_FAILED: result = -4800; break; case OSPC_ERR_SOCK_SELECT_FAILED: result = -4801; break; case OSPC_ERR_HTTP_SERVER_NOT_READY: result = -4802; break; case OSPC_ERR_TRAN_CALLED_FILTERING: result = -4840; break; case OSPC_ERR_HTTP_SERVICE_UNAVAILABLE: result = -5030; break; case OSPC_ERR_TRAN_DECLINE: result = -6030; break; case OSPC_ERR_NO_ERROR: /* AuthRsp ok but ospLoadRoutes fails */ result = MODULE_RETURNCODE_ERROR; break; default: result = MODULE_RETURNCODE_FALSE; break; } } } if (callids[0] != NULL) { OSPPCallIdDelete(&(callids[0])); } if (trans != -1) { OSPPTransactionDelete(trans); } return result; }
static void trace_onreply_in(struct cell* t, int type, struct tmcb_params *ps) { db_key_t db_keys[NR_KEYS]; db_val_t db_vals[NR_KEYS]; static char fromip_buff[IP_ADDR_MAX_STR_SIZE+12]; static char toip_buff[IP_ADDR_MAX_STR_SIZE+12]; struct sip_msg* msg; struct sip_msg* req; int_str avp_value; struct usr_avp *avp; char statusbuf[8]; if(t==NULL || t->uas.request==0 || ps==NULL) { LM_DBG("no uas request, local transaction\n"); return; } req = ps->req; msg = ps->rpl; if(msg==NULL || req==NULL) { LM_DBG("no reply\n"); return; } avp = NULL; if(traced_user_avp.n!=0) avp=search_first_avp(traced_user_avp_type, traced_user_avp, &avp_value, 0); if((avp==NULL) && trace_is_off(req)) { LM_DBG("trace off...\n"); return; } if(parse_from_header(msg)==-1 || msg->from==NULL || get_from(msg)==NULL) { LM_ERR("cannot parse FROM header\n"); goto error; } if(parse_headers(msg, HDR_CALLID_F, 0)!=0) { LM_ERR("cannot parse call-id\n"); return; } db_keys[0] = msg_column; db_vals[0].type = DB_BLOB; db_vals[0].nul = 0; if(msg->len>0) { db_vals[0].val.blob_val.s = msg->buf; db_vals[0].val.blob_val.len = msg->len; } else { db_vals[0].val.blob_val.s = "No reply buffer"; db_vals[0].val.blob_val.len = sizeof("No reply buffer")-1; } /* check Call-ID header */ if(msg->callid==NULL || msg->callid->body.s==NULL) { LM_ERR("cannot find Call-ID header!\n"); goto error; } db_keys[1] = callid_column; db_vals[1].type = DB_STR; db_vals[1].nul = 0; db_vals[1].val.str_val.s = msg->callid->body.s; db_vals[1].val.str_val.len = msg->callid->body.len; db_keys[2] = method_column; db_vals[2].type = DB_STR; db_vals[2].nul = 0; db_vals[2].val.str_val.s = t->method.s; db_vals[2].val.str_val.len = t->method.len; db_keys[3] = status_column; db_vals[3].type = DB_STRING; db_vals[3].nul = 0; strcpy(statusbuf, int2str(ps->code, NULL)); db_vals[3].val.string_val = statusbuf; db_keys[4] = fromip_column; db_vals[4].type = DB_STRING; db_vals[4].nul = 0; siptrace_copy_proto(msg->rcv.proto, fromip_buff); strcat(fromip_buff, ip_addr2a(&msg->rcv.src_ip)); strcat(fromip_buff,":"); strcat(fromip_buff, int2str(msg->rcv.src_port, NULL)); db_vals[4].val.string_val = fromip_buff; db_keys[5] = toip_column; db_vals[5].type = DB_STRING; db_vals[5].nul = 0; // db_vals[5].val.string_val = ip_addr2a(&msg->rcv.dst_ip);; if(trace_local_ip) db_vals[5].val.string_val = trace_local_ip; else { siptrace_copy_proto(msg->rcv.proto, toip_buff); strcat(toip_buff, ip_addr2a(&msg->rcv.dst_ip)); strcat(toip_buff,":"); strcat(toip_buff, int2str(msg->rcv.dst_port, NULL)); db_vals[5].val.string_val = toip_buff; } db_keys[6] = date_column; db_vals[6].type = DB_DATETIME; db_vals[6].nul = 0; db_vals[6].val.time_val = time(NULL); db_keys[7] = direction_column; db_vals[7].type = DB_STRING; db_vals[7].nul = 0; db_vals[7].val.string_val = "in"; db_keys[8] = fromtag_column; db_vals[8].type = DB_STR; db_vals[8].nul = 0; db_vals[8].val.str_val.s = get_from(msg)->tag_value.s; db_vals[8].val.str_val.len = get_from(msg)->tag_value.len; db_funcs.use_table(db_con, siptrace_get_table()); db_keys[9] = traced_user_column; db_vals[9].type = DB_STR; db_vals[9].nul = 0; if( !trace_is_off(req) ) { db_vals[9].val.str_val.s = ""; db_vals[9].val.str_val.len = 0; LM_DBG("storing info...\n"); if(db_funcs.insert(db_con, db_keys, db_vals, NR_KEYS) < 0) { LM_ERR("error storing trace\n"); goto error; } #ifdef STATISTICS update_stat(siptrace_rpl, 1); #endif } if(avp==NULL) goto done; trace_send_duplicate(db_vals[0].val.blob_val.s, db_vals[0].val.blob_val.len); db_vals[9].val.str_val.s = avp_value.s.s; db_vals[9].val.str_val.len = avp_value.s.len; LM_DBG("storing info...\n"); if(db_funcs.insert(db_con, db_keys, db_vals, NR_KEYS) < 0) { LM_ERR("error storing trace\n"); goto error; } avp = search_next_avp( avp, &avp_value); while(avp!=NULL) { db_vals[9].val.str_val.s = avp_value.s.s; db_vals[9].val.str_val.len = avp_value.s.len; LM_DBG("storing info ...\n"); if(db_funcs.insert(db_con, db_keys, db_vals, NR_KEYS) < 0) { LM_ERR("error storing trace\n"); goto error; } avp = search_next_avp( avp, &avp_value); } done: return; error: return; }
/* * Request OSP authorization and routeing * param msg SIP message * param ignore1 * param ignore2 * return MODULE_RETURNCODE_TRUE success, MODULE_RETURNCODE_FALSE failure, MODULE_RETURNCODE_ERROR error */ int ospRequestRouting( struct sip_msg* msg, char* ignore1, char* ignore2) { int errcode; time_t authtime; char calling[OSP_STRBUF_SIZE]; char called[OSP_STRBUF_SIZE]; char rn[OSP_STRBUF_SIZE]; char cic[OSP_STRBUF_SIZE]; int npdi; OSPE_OPERATOR_NAME type; char opname[OSPC_OPNAME_NUMBER][OSP_STRBUF_SIZE]; char source[OSP_STRBUF_SIZE]; char sourcebuf[OSP_STRBUF_SIZE]; char srcdev[OSP_STRBUF_SIZE]; char srcdevbuf[OSP_STRBUF_SIZE]; char rpid[OSP_STRBUF_SIZE]; char pai[OSP_STRBUF_SIZE]; char divuser[OSP_STRBUF_SIZE]; char divhost[OSP_STRBUF_SIZE]; char divhostbuf[OSP_STRBUF_SIZE]; char pci[OSP_STRBUF_SIZE]; struct usr_avp* snidavp = NULL; int_str snidval; char snid[OSP_STRBUF_SIZE]; struct usr_avp* cinfoavp = NULL; int_str cinfoval; unsigned int cinfonum = 0, i; char cinfo[OSP_DEF_CINFOS][OSP_STRBUF_SIZE]; char cinfostr[OSP_STRBUF_SIZE]; unsigned int callidnumber = 1; OSPT_CALL_ID* callids[callidnumber]; unsigned int logsize = 0; char* detaillog = NULL; char tohost[OSP_STRBUF_SIZE]; char tohostbuf[OSP_STRBUF_SIZE]; const char* preferred[2] = { NULL }; unsigned int destcount; OSPTTRANHANDLE trans = -1; int result = MODULE_RETURNCODE_FALSE; if ((errcode = OSPPTransactionNew(_osp_provider, &trans)) != OSPC_ERR_NO_ERROR) { LM_ERR("failed to create new OSP transaction (%d)\n", errcode); } else if (ospGetFromUserpart(msg, calling, sizeof(calling)) != 0) { LM_ERR("failed to extract calling number\n"); } else if ((ospGetUriUserpart(msg, called, sizeof(called)) != 0) && (ospGetToUserpart(msg, called, sizeof(called)) != 0)) { LM_ERR("failed to extract called number\n"); } else if (ospGetCallId(msg, &(callids[0])) != 0) { LM_ERR("failed to extract call id\n"); } else if (ospGetSource(msg, source, sizeof(source)) != 0) { LM_ERR("failed to extract source address\n"); } else if (ospGetSourceDevice(msg, srcdev, sizeof(srcdev)) != 0) { LM_ERR("failed to extract source deivce address\n"); } else { authtime = time(NULL); ospConvertToOutAddress(source, sourcebuf, sizeof(sourcebuf)); ospConvertToOutAddress(srcdev, srcdevbuf, sizeof(srcdevbuf)); switch (_osp_service_type) { case 1: OSPPTransactionSetServiceType(trans, OSPC_SERVICE_NPQUERY); ospGetToHostpart(msg, tohost, sizeof(tohost)); ospConvertToOutAddress(tohost, tohostbuf, sizeof(tohostbuf)); preferred[0] = tohostbuf; destcount = 1; break; case 0: default: OSPPTransactionSetServiceType(trans, OSPC_SERVICE_VOICE); destcount = _osp_max_dests; break; } if (ospGetNpParameters(msg, rn, sizeof(rn), cic, sizeof(cic), &npdi) == 0) { OSPPTransactionSetNumberPortability(trans, rn, cic, npdi); } for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) { if (ospGetOperatorName(msg, type, opname[type], sizeof(opname[type])) == 0) { OSPPTransactionSetOperatorName(trans, type, opname[type]); } } if (ospGetRpidUserpart(msg, rpid, sizeof(rpid)) == 0) { OSPPTransactionSetRemotePartyId(trans, OSPC_NFORMAT_E164, rpid); } if (ospGetPaiUserpart(msg, pai, sizeof(pai)) == 0) { OSPPTransactionSetAssertedId(trans, OSPC_NFORMAT_E164, pai); } if (ospGetDiversion(msg, divuser, sizeof(divuser), divhost, sizeof(divhost)) == 0) { ospConvertToOutAddress(divhost, divhostbuf, sizeof(divhostbuf)); } else { divhostbuf[0] = '\0'; } OSPPTransactionSetDiversion(trans, divuser, divhostbuf); OSPPTransactionSetProtocol(trans, OSPC_PROTTYPE_SOURCE, OSPC_PROTNAME_SIP); if (ospGetPChargeInfoUserpart(msg, pci, sizeof(pci)) == 0) { OSPPTransactionSetChargeInfo(trans, OSPC_NFORMAT_E164, pci); } if ((_osp_snid_avpid >= 0) && ((snidavp = search_first_avp(_osp_snid_avptype, _osp_snid_avpid, &snidval, 0)) != NULL) && (snidavp->flags & AVP_VAL_STR) && (snidval.s.s && snidval.s.len)) { snprintf(snid, sizeof(snid), "%.*s", snidval.s.len, snidval.s.s); snid[sizeof(snid) - 1] = '\0'; OSPPTransactionSetNetworkIds(trans, snid, ""); } else { snid[0] = '\0'; } if (_osp_cinfo_avpid >= 0) { for (i = 0, cinfoavp = search_first_avp(_osp_cinfo_avptype, _osp_cinfo_avpid, NULL, 0); ((i < OSP_DEF_CINFOS) && (cinfoavp != NULL)); i++, cinfoavp = search_next_avp(cinfoavp, NULL)) { get_avp_val(cinfoavp, &cinfoval); if ((cinfoavp->flags & AVP_VAL_STR) && (cinfoval.s.s && cinfoval.s.len)) { snprintf(cinfo[i], sizeof(cinfo[i]), "%.*s", cinfoval.s.len, cinfoval.s.s); cinfo[i][sizeof(cinfo[i]) - 1] = '\0'; } else { cinfo[i][0] = '\0'; } } cinfonum = i; cinfostr[0] = '\0'; for (i = 0; i < cinfonum; i++) { if (cinfo[cinfonum - i - 1][0] != '\0') { OSPPTransactionSetCustomInfo(trans, i, cinfo[cinfonum - i - 1]); snprintf(cinfostr + strlen(cinfostr), sizeof(cinfostr) - strlen(cinfostr), "custom_info%d '%s' ", i + 1, cinfo[cinfonum - i - 1]); } } cinfostr[sizeof(cinfostr) - 1] = '\0'; } LM_INFO("request auth and routing for: " "service_type '%d' " "source '%s' " "source_dev '%s' " "source_networkid '%s' " "calling '%s' " "called '%s' " "preferred '%s' " "nprn '%s' " "npcic '%s' " "npdi '%d' " /* "spid '%s' " "ocn '%s' " "spn '%s' " "altspn '%s' " "mcc '%s' " "mnc '%s' " */ "rpid '%s' " "pai '%s' " "div_user '%s' " "div_host '%s' " "pci '%s' " "call_id '%.*s' " "dest_count '%d' " "%s\n", _osp_service_type, sourcebuf, srcdevbuf, snid, calling, called, (preferred[0] == NULL) ? "" : preferred[0], rn, cic, npdi, /* opname[OSPC_OPNAME_SPID], opname[OSPC_OPNAME_OCN], opname[OSPC_OPNAME_SPN], opname[OSPC_OPNAME_ALTSPN], opname[OSPC_OPNAME_MCC], opname[OSPC_OPNAME_MNC], */ rpid, pai, divuser, divhostbuf, pci, callids[0]->Length, callids[0]->Value, destcount, cinfostr); /* try to request authorization */ errcode = OSPPTransactionRequestAuthorisation( trans, /* transaction handle */ sourcebuf, /* from the configuration file */ srcdevbuf, /* source device of call, protocol specific, in OSP format */ calling, /* calling number in nodotted e164 notation */ OSPC_NFORMAT_E164, /* calling number format */ called, /* called number */ OSPC_NFORMAT_E164, /* called number format */ "", /* optional username string, used if no number */ callidnumber, /* number of call ids, here always 1 */ callids, /* sized-1 array of call ids */ preferred, /* preferred destinations */ &destcount, /* max destinations, after call dest_count */ &logsize, /* size allocated for detaillog (next param) 0=no log */ detaillog); /* memory location for detaillog to be stored */ if ((errcode == OSPC_ERR_NO_ERROR) && (ospLoadRoutes(trans, destcount, source, srcdev, called, authtime, rpid, pai, divuser, divhostbuf, pci) == 0)) { LM_INFO("there are '%d' OSP routes, call_id '%.*s'\n", destcount, callids[0]->Length, callids[0]->Value); result = MODULE_RETURNCODE_TRUE; } else { LM_ERR("failed to request auth and routing (%d), call_id '%.*s'\n", errcode, callids[0]->Length, callids[0]->Value); switch (errcode) { case OSPC_ERR_TRAN_ROUTE_BLOCKED: result = -403; break; case OSPC_ERR_TRAN_ROUTE_NOT_FOUND: result = -404; break; case OSPC_ERR_TRAN_CALLING_INVALID: result = -428; break; case OSPC_ERR_TRAN_CALLED_FILTERING: result = -484; break; case OSPC_ERR_NO_ERROR: /* AuthRsp ok but ospLoadRoutes fails */ result = MODULE_RETURNCODE_ERROR; break; default: result = MODULE_RETURNCODE_FALSE; break; } } } if (callids[0] != NULL) { OSPPCallIdDelete(&(callids[0])); } if (trans != -1) { OSPPTransactionDelete(trans); } return result; }
/*! \brief * Adds to request a destination set that includes all highest priority * class contacts in "serial_avp" AVP. If called from a route block, * rewrites the request uri with first contact and adds the remaining * contacts as branches. If called from failure route block, adds all * contacts as brances. Removes added contacts from "serial_avp" AVP. */ int next_branches( struct sip_msg *msg) { struct usr_avp *avp, *prev; int_str val; struct socket_info *sock_info; qvalue_t q; str uri, dst_uri, path; char *p; unsigned int flags; int rval; if (route_type != REQUEST_ROUTE && route_type != FAILURE_ROUTE ) { /* unsupported route type */ LM_ERR("called from unsupported route type %d\n", route_type); goto error; } /* Find first avp */ avp = search_first_avp(0, serial_avp, &val, 0); if (!avp) { LM_DBG("no AVPs -- we are done!\n"); goto error; } if (!val.s.s) { LM_ERR("invalid avp value\n"); goto error; } /* *sock_info, flags, q, uri, 0, dst_uri, 0, path, 0,... */ p = val.s.s; sock_info = (struct socket_info*) *((long*) p); p += sizeof(long); flags = (unsigned int) *((long*) p); p += sizeof(long); q = (unsigned int) *((long*) p); p += sizeof(long); uri.s = p; uri.len = strlen(p); p += uri.len + 1; dst_uri.s = p; dst_uri.len = strlen(p); p += dst_uri.len + 1; path.s = p; path.len = strlen(p); /* Set Request-URI */ if ( set_ruri(msg, &uri) == -1 || set_dst_uri(msg, &dst_uri) == -1 || set_path_vector(msg, &path) == -1 ) goto error1; msg->force_send_socket = sock_info; set_ruri_q( q ); setb0flags( flags ); LM_DBG("Msg information <%.*s,%.*s,%.*s,%d,%u> (avp flag=%u)\n", uri.len, uri.s, dst_uri.len, dst_uri.s, path.len, path.s, q, flags, avp->flags); if (avp->flags & Q_FLAG) { destroy_avp(avp); goto done; } prev = avp; avp = search_next_avp(prev, &val); destroy_avp(prev); /* Append branches until out of branches or Q_FLAG is set */ while (avp != NULL) { if (!val.s.s) { LM_ERR("invalid avp value\n"); continue; } p = val.s.s; sock_info = (struct socket_info*) *((long*) p); p += sizeof(long); flags = (unsigned int) *((long*) p); p += sizeof(long); q = (unsigned int) *((long*) p); p += sizeof(long); uri.s = p; uri.len = strlen(p); p += strlen(p) + 1; dst_uri.s = p; dst_uri.len = strlen(p); p += strlen(p) + 1; path.s = p; path.len = strlen(p); LM_DBG("Branch information <%.*s,%.*s,%.*s,%d,%u> (avp flag=%u)\n", uri.len, uri.s, dst_uri.len, dst_uri.s, path.len, path.s, q, flags, avp->flags); rval = append_branch(msg, &uri, &dst_uri, &path, q, flags, sock_info); if (rval == -1) { LM_ERR("append_branch failed\n"); goto error1; } if (avp->flags & Q_FLAG) { destroy_avp(avp); goto done; } prev = avp; avp = search_next_avp(prev, &val); destroy_avp(prev); } return 2; done: return (search_next_avp(avp, NULL)==NULL)?2:1; error1: destroy_avp(avp); error: return -1; }
static void trace_sl_onreply_out( unsigned int types, struct sip_msg* req, struct sl_cb_param *sl_param) { db_key_t db_keys[NR_KEYS]; db_val_t db_vals[NR_KEYS]; static char fromip_buff[IP_ADDR_MAX_STR_SIZE+12]; static char toip_buff[IP_ADDR_MAX_STR_SIZE+12]; int faked = 0; struct sip_msg* msg; int_str avp_value; struct usr_avp *avp; struct ip_addr to_ip; int len; char statusbuf[5]; if(req==NULL || sl_param==NULL) { LM_ERR("bad parameters\n"); goto error; } avp = NULL; if(traced_user_avp.n!=0) avp=search_first_avp(traced_user_avp_type, traced_user_avp, &avp_value, 0); if((avp==NULL) && trace_is_off(req)) { LM_DBG("trace off...\n"); return; } msg = req; faked = 1; if(parse_from_header(msg)==-1 || msg->from==NULL || get_from(msg)==NULL) { LM_ERR("cannot parse FROM header\n"); goto error; } if(parse_headers(msg, HDR_CALLID_F, 0)!=0) { LM_ERR("cannot parse call-id\n"); return; } db_keys[0] = msg_column; db_vals[0].type = DB_BLOB; db_vals[0].nul = 0; db_vals[0].val.blob_val.s = (sl_param->buffer)?sl_param->buffer->s:""; db_vals[0].val.blob_val.len = (sl_param->buffer)?sl_param->buffer->len:0; /* check Call-ID header */ if(msg->callid==NULL || msg->callid->body.s==NULL) { LM_ERR("cannot find Call-ID header!\n"); goto error; } db_keys[1] = callid_column; db_vals[1].type = DB_STR; db_vals[1].nul = 0; db_vals[1].val.str_val.s = msg->callid->body.s; db_vals[1].val.str_val.len = msg->callid->body.len; db_keys[2] = method_column; db_vals[2].type = DB_STR; db_vals[2].nul = 0; db_vals[2].val.str_val.s = msg->first_line.u.request.method.s; db_vals[2].val.str_val.len = msg->first_line.u.request.method.len; db_keys[4] = fromip_column; db_vals[4].type = DB_STRING; db_vals[4].nul = 0; if(trace_local_ip) db_vals[4].val.string_val = trace_local_ip; else { siptrace_copy_proto(msg->rcv.proto, fromip_buff); strcat(fromip_buff, ip_addr2a(&req->rcv.dst_ip)); strcat(fromip_buff,":"); strcat(fromip_buff, int2str(req->rcv.dst_port, NULL)); db_vals[4].val.string_val = fromip_buff; } db_keys[3] = status_column; db_vals[3].type = DB_STRING; db_vals[3].nul = 0; strcpy(statusbuf, int2str(sl_param->code, NULL)); db_vals[3].val.string_val = statusbuf; db_keys[5] = toip_column; db_vals[5].type = DB_STRING; db_vals[5].nul = 0; memset(&to_ip, 0, sizeof(struct ip_addr)); if(sl_param->dst==0) { db_vals[5].val.string_val = "any:255.255.255.255"; } else { su2ip_addr(&to_ip, sl_param->dst); siptrace_copy_proto(req->rcv.proto, toip_buff); strcat(toip_buff, ip_addr2a(&to_ip)); strcat(toip_buff, ":"); strcat(toip_buff, int2str((unsigned long)su_getport(sl_param->dst), &len)); LM_DBG("dest [%s]\n", toip_buff); db_vals[5].val.string_val = toip_buff; } db_keys[6] = date_column; db_vals[6].type = DB_DATETIME; db_vals[6].nul = 0; db_vals[6].val.time_val = time(NULL); db_keys[7] = direction_column; db_vals[7].type = DB_STRING; db_vals[7].nul = 0; db_vals[7].val.string_val = "out"; db_keys[8] = fromtag_column; db_vals[8].type = DB_STR; db_vals[8].nul = 0; db_vals[8].val.str_val.s = get_from(msg)->tag_value.s; db_vals[8].val.str_val.len = get_from(msg)->tag_value.len; db_funcs.use_table(db_con, siptrace_get_table()); db_keys[9] = traced_user_column; db_vals[9].type = DB_STR; db_vals[9].nul = 0; if( !trace_is_off(msg) ) { db_vals[9].val.str_val.s = ""; db_vals[9].val.str_val.len = 0; LM_DBG("storing info...\n"); if(db_funcs.insert(db_con, db_keys, db_vals, NR_KEYS) < 0) { LM_ERR("error storing trace\n"); goto error; } #ifdef STATISTICS update_stat(siptrace_rpl, 1); #endif } if(avp==NULL) goto done; trace_send_duplicate(db_vals[0].val.blob_val.s, db_vals[0].val.blob_val.len); db_vals[9].val.str_val.s = avp_value.s.s; db_vals[9].val.str_val.len = avp_value.s.len; LM_DBG("storing info...\n"); if(db_funcs.insert(db_con, db_keys, db_vals, NR_KEYS) < 0) { LM_ERR("error storing trace\n"); goto error; } avp = search_next_avp( avp, &avp_value); while(avp!=NULL) { db_vals[9].val.str_val.s = avp_value.s.s; db_vals[9].val.str_val.len = avp_value.s.len; LM_DBG("### - storing info (%d) ...\n", faked); if(db_funcs.insert(db_con, db_keys, db_vals, NR_KEYS) < 0) { LM_ERR("error storing trace\n"); goto error; } avp = search_next_avp( avp, &avp_value); } done: return; error: return; }
static void trace_onreply_out(struct cell* t, int type, struct tmcb_params *ps) { db_key_t db_keys[NR_KEYS]; db_val_t db_vals[NR_KEYS]; int faked = 0; static char fromip_buff[IP_ADDR_MAX_STR_SIZE+12]; static char toip_buff[IP_ADDR_MAX_STR_SIZE+12]; struct sip_msg* msg; struct sip_msg* req; int_str avp_value; struct usr_avp *avp; struct ip_addr to_ip; int len; char statusbuf[8]; str *sbuf; struct dest_info *dst; if (t==NULL || t->uas.request==0 || ps==NULL) { LM_DBG("no uas request, local transaction\n"); return; } avp = NULL; if(traced_user_avp.n!=0) avp=search_first_avp(traced_user_avp_type, traced_user_avp, &avp_value, 0); if((avp==NULL) && trace_is_off(t->uas.request)) { LM_DBG("trace off...\n"); return; } req = ps->req; msg = ps->rpl; if(msg==NULL || msg==FAKED_REPLY) { msg = t->uas.request; faked = 1; } if(parse_from_header(msg)==-1 || msg->from==NULL || get_from(msg)==NULL) { LM_ERR("cannot parse FROM header\n"); goto error; } if(parse_headers(msg, HDR_CALLID_F, 0)!=0) { LM_ERR("cannot parse call-id\n"); return; } db_keys[0] = msg_column; db_vals[0].type = DB_BLOB; db_vals[0].nul = 0; sbuf = (str*)ps->extra1; if(faked==0) { if(sbuf!=0 && sbuf->len>0) { db_vals[0].val.blob_val.s = sbuf->s; db_vals[0].val.blob_val.len = sbuf->len; } else if(t->uas.response.buffer.s!=NULL) { db_vals[0].val.blob_val.s = t->uas.response.buffer.s; db_vals[0].val.blob_val.len = t->uas.response.buffer.len; } else if(msg->len>0) { db_vals[0].val.blob_val.s = msg->buf; db_vals[0].val.blob_val.len = msg->len; } else { db_vals[0].val.blob_val.s = "No reply buffer"; db_vals[0].val.blob_val.len = sizeof("No reply buffer")-1; } } else { if(sbuf!=0 && sbuf->len>0) { db_vals[0].val.blob_val.s = sbuf->s; db_vals[0].val.blob_val.len = sbuf->len; } else if(t->uas.response.buffer.s==NULL) { db_vals[0].val.blob_val.s = "No reply buffer"; db_vals[0].val.blob_val.len = sizeof("No reply buffer")-1; } else { db_vals[0].val.blob_val.s = t->uas.response.buffer.s; db_vals[0].val.blob_val.len = t->uas.response.buffer.len; } } /* check Call-ID header */ if(msg->callid==NULL || msg->callid->body.s==NULL) { LM_ERR("cannot find Call-ID header!\n"); goto error; } db_keys[1] = callid_column; db_vals[1].type = DB_STR; db_vals[1].nul = 0; db_vals[1].val.str_val.s = msg->callid->body.s; db_vals[1].val.str_val.len = msg->callid->body.len; db_keys[2] = method_column; db_vals[2].type = DB_STR; db_vals[2].nul = 0; db_vals[2].val.str_val.s = t->method.s; db_vals[2].val.str_val.len = t->method.len; db_keys[4] = fromip_column; db_vals[4].type = DB_STRING; db_vals[4].nul = 0; if(trace_local_ip) db_vals[4].val.string_val = trace_local_ip; else { siptrace_copy_proto(msg->rcv.proto, fromip_buff); strcat(fromip_buff, ip_addr2a(&req->rcv.dst_ip)); strcat(fromip_buff,":"); strcat(fromip_buff, int2str(req->rcv.dst_port, NULL)); db_vals[4].val.string_val = fromip_buff; } db_keys[3] = status_column; db_vals[3].type = DB_STRING; db_vals[3].nul = 0; strcpy(statusbuf, int2str(ps->code, NULL)); db_vals[3].val.string_val = statusbuf; db_keys[5] = toip_column; db_vals[5].type = DB_STRING; db_vals[5].nul = 0; memset(&to_ip, 0, sizeof(struct ip_addr)); dst = (struct dest_info*)ps->extra2; if(dst==0) { db_vals[5].val.string_val = "any:255.255.255.255"; } else { su2ip_addr(&to_ip, &dst->to); siptrace_copy_proto(dst->proto, toip_buff); strcat(toip_buff, ip_addr2a(&to_ip)); strcat(toip_buff, ":"); strcat(toip_buff, int2str((unsigned long)su_getport(&dst->to), &len)); LM_DBG("dest [%s]\n", toip_buff); db_vals[5].val.string_val = toip_buff; } db_keys[6] = date_column; db_vals[6].type = DB_DATETIME; db_vals[6].nul = 0; db_vals[6].val.time_val = time(NULL); db_keys[7] = direction_column; db_vals[7].type = DB_STRING; db_vals[7].nul = 0; db_vals[7].val.string_val = "out"; db_keys[8] = fromtag_column; db_vals[8].type = DB_STR; db_vals[8].nul = 0; db_vals[8].val.str_val.s = get_from(msg)->tag_value.s; db_vals[8].val.str_val.len = get_from(msg)->tag_value.len; db_funcs.use_table(db_con, siptrace_get_table()); db_keys[9] = traced_user_column; db_vals[9].type = DB_STR; db_vals[9].nul = 0; if( !trace_is_off(req) ) { db_vals[9].val.str_val.s = ""; db_vals[9].val.str_val.len = 0; LM_DBG("storing info...\n"); if(db_funcs.insert(db_con, db_keys, db_vals, NR_KEYS) < 0) { LM_ERR("error storing trace\n"); goto error; } #ifdef STATISTICS update_stat(siptrace_rpl, 1); #endif } if(avp==NULL) goto done; trace_send_duplicate(db_vals[0].val.blob_val.s, db_vals[0].val.blob_val.len); db_vals[9].val.str_val.s = avp_value.s.s; db_vals[9].val.str_val.len = avp_value.s.len; LM_DBG("storing info...\n"); if(db_funcs.insert(db_con, db_keys, db_vals, NR_KEYS) < 0) { LM_ERR("error storing trace\n"); goto error; } avp = search_next_avp( avp, &avp_value); while(avp!=NULL) { db_vals[9].val.str_val.s = avp_value.s.s; db_vals[9].val.str_val.len = avp_value.s.len; LM_DBG("### - storing info (%d) ...\n", faked); if(db_funcs.insert(db_con, db_keys, db_vals, NR_KEYS) < 0) { LM_ERR("error storing trace\n"); goto error; } avp = search_next_avp( avp, &avp_value); } done: return; error: return; }
static int trace_dialog(struct sip_msg *msg) { unsigned char n; struct dlg_cell* dlg; struct usr_avp *avp; static int_str avp_value; str *name; if (!msg) { LM_ERR("no msg specified\n"); return -1; } if (trace_is_off()) { LM_DBG("Trace if off...\n"); return -1; } /* any need to do tracing here ? check the triggers */ avp = traced_user_avp<0 ? NULL : search_first_avp(traced_user_avp_type, traced_user_avp, &avp_value, 0); if (avp==NULL && (msg->flags&trace_flag)==0) { LM_DBG("Nothing to trace here\n"); return -1; } if (dlgb.create_dlg(msg,0)<1) { LM_ERR("failed to create dialog\n"); return -1; } dlg = dlgb.get_dlg(); if (dlg==NULL) { LM_CRIT("BUG: no dialog found after create dialog\n"); return -1; } if(dlgb.register_dlgcb(dlg, DLGCB_REQ_WITHIN|DLGCB_TERMINATED, trace_transaction,0,0)!=0) { LM_ERR("failed to register dialog callback\n"); return -1; } /* store in dialog the user avps for tracing ; we will restore them for each transactin from the dialog */ if(traced_user_avp>=0) { n = 0; while(avp!=NULL) { /* generate a name */ name = generate_val_name(n); if (!is_avp_str_val(avp)) avp_value.s.s=int2str(avp_value.n, &avp_value.s.len); /* add the avp value as dialog var */ dlgb.store_dlg_value( dlg, name, &avp_value.s); /* next avp */ avp = search_next_avp( avp, &avp_value); n++; } } /* set the flag to trace the rest of the transaction */ if (msg->flags&trace_flag) { avp_value.s.s = "1"; avp_value.s.len = 1; dlgb.store_dlg_value( dlg, &st_flag_val, &avp_value.s); } /* trace current request */ sip_trace(msg); /* we also want to catch the incoming cancel */ if ( tmb.register_tmcb( msg, NULL,TMCB_TRANS_CANCELLED, siptrace_dlg_cancel, NULL, NULL)<0 ) { LM_ERR("failed to register trans cancelled TMCB\n"); } return 1; }
static int sip_trace(struct sip_msg *msg, char *s1, char *s2) { db_key_t db_keys[NR_KEYS]; db_val_t db_vals[NR_KEYS]; static char toip_buff[IP_ADDR_MAX_STR_SIZE+6]; static char fromip_buff[IP_ADDR_MAX_STR_SIZE+6]; int_str avp_value; struct usr_avp *avp; if(msg==NULL) { LM_DBG("no uas request, local transaction\n"); return -1; } avp = NULL; if(traced_user_avp.n!=0) avp=search_first_avp(traced_user_avp_type, traced_user_avp, &avp_value, 0); if((avp==NULL) && (trace_on_flag==NULL || *trace_on_flag==0)) { LM_DBG("trace off...\n"); return -1; } if(parse_from_header(msg)==-1 || msg->from==NULL || get_from(msg)==NULL) { LM_ERR("cannot parse FROM header\n"); goto error; } if(parse_headers(msg, HDR_CALLID_F, 0)!=0 || msg->callid==NULL || msg->callid->body.s==NULL) { LM_ERR("cannot parse call-id\n"); goto error; } db_keys[0] = msg_column; db_vals[0].type = DB_BLOB; db_vals[0].nul = 0; db_vals[0].val.blob_val.s = msg->buf; db_vals[0].val.blob_val.len = msg->len; db_keys[1] = callid_column; db_vals[1].type = DB_STR; db_vals[1].nul = 0; db_vals[1].val.str_val.s = msg->callid->body.s; db_vals[1].val.str_val.len = msg->callid->body.len; db_keys[2] = method_column; db_vals[2].type = DB_STR; db_vals[2].nul = 0; if(msg->first_line.type==SIP_REQUEST) { db_vals[2].val.str_val.s = msg->first_line.u.request.method.s; db_vals[2].val.str_val.len = msg->first_line.u.request.method.len; } else { db_vals[2].val.str_val.s = ""; db_vals[2].val.str_val.len = 0; } db_keys[3] = status_column; db_vals[3].type = DB_STR; db_vals[3].nul = 0; if(msg->first_line.type==SIP_REPLY) { db_vals[3].val.str_val.s = msg->first_line.u.reply.status.s; db_vals[3].val.str_val.len = msg->first_line.u.reply.status.len; } else { db_vals[3].val.str_val.s = ""; db_vals[3].val.str_val.len = 0; } db_keys[4] = fromip_column; db_vals[4].type = DB_STRING; db_vals[4].nul = 0; siptrace_copy_proto(msg->rcv.proto, fromip_buff); strcat(fromip_buff, ip_addr2a(&msg->rcv.src_ip)); strcat(fromip_buff,":"); strcat(fromip_buff, int2str(msg->rcv.src_port, NULL)); db_vals[4].val.string_val = fromip_buff; db_keys[5] = toip_column; db_vals[5].type = DB_STRING; db_vals[5].nul = 0; // db_vals[5].val.string_val = ip_addr2a(&msg->rcv.dst_ip);; siptrace_copy_proto(msg->rcv.proto, toip_buff); strcat(toip_buff, ip_addr2a(&msg->rcv.dst_ip)); strcat(toip_buff,":"); strcat(toip_buff, int2str(msg->rcv.dst_port, NULL)); db_vals[5].val.string_val = toip_buff; db_keys[6] = date_column; db_vals[6].type = DB_DATETIME; db_vals[6].nul = 0; db_vals[6].val.time_val = time(NULL); db_keys[7] = direction_column; db_vals[7].type = DB_STRING; db_vals[7].nul = 0; db_vals[7].val.string_val = "in"; db_keys[8] = fromtag_column; db_vals[8].type = DB_STR; db_vals[8].nul = 0; db_vals[8].val.str_val.s = get_from(msg)->tag_value.s; db_vals[8].val.str_val.len = get_from(msg)->tag_value.len; db_funcs.use_table(db_con, siptrace_get_table()); db_keys[9] = traced_user_column; db_vals[9].type = DB_STR; db_vals[9].nul = 0; if(trace_on_flag!=NULL && *trace_on_flag!=0) { db_vals[9].val.str_val.s = ""; db_vals[9].val.str_val.len = 0; LM_DBG("storing info...\n"); if(db_funcs.insert(db_con, db_keys, db_vals, NR_KEYS) < 0) { LM_ERR("error storing trace\n"); goto error; } #ifdef STATISTICS if(msg->first_line.type==SIP_REPLY) { update_stat(siptrace_rpl, 1); } else { update_stat(siptrace_req, 1); } #endif } if(avp==NULL) goto done; trace_send_duplicate(db_vals[0].val.blob_val.s, db_vals[0].val.blob_val.len); db_vals[9].val.str_val.s = avp_value.s.s; db_vals[9].val.str_val.len = avp_value.s.len; LM_DBG("storing info...\n"); if(db_funcs.insert(db_con, db_keys, db_vals, NR_KEYS) < 0) { LM_ERR("error storing trace\n"); goto error; } avp = search_next_avp( avp, &avp_value); while(avp!=NULL) { db_vals[9].val.str_val.s = avp_value.s.s; db_vals[9].val.str_val.len = avp_value.s.len; LM_DBG("storing info...\n"); if(db_funcs.insert(db_con, db_keys, db_vals, NR_KEYS) < 0) { LM_ERR("error storing trace\n"); goto error; } avp = search_next_avp( avp, &avp_value); } done: return 1; error: return -1; }