/* * 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; }
static void dump_domain(rpc_t* rpc, void* ctx, domain_t* d) { avp_t* a; void* st; int i; str* name; int_str val; if (rpc->add(ctx, "{", &st) < 0) return; if (rpc->struct_add(st, "S", "did", &d->did) < 0) return; for(i = 0; i < d->n; i++) { if (rpc->struct_add(st, "S", "domain", &d->domain[i]) < 0) return; if (rpc->struct_add(st, "d", "flags", d->flags[i]) < 0) return; } a = d->attrs; while(a) { name = get_avp_name(a); get_avp_val(a, &val); if (a->flags & AVP_VAL_STR) { if (rpc->struct_printf(st, "attr", "%.*s=%.*s", STR_FMT(name), STR_FMT(&val.s)) < 0) return; } else { if (rpc->struct_printf(st, "attr", "%.*s=%d", STR_FMT(name), val.n) < 0) return; } a = a->next; } }
int ops_print_avp(void) { struct usr_avp **avp_list; struct usr_avp *avp; int_str val; str *name; /* go through all list */ avp_list = get_avp_list(); avp = *avp_list; for ( ; avp ; avp=avp->next) { LM_INFO("p=%p, flags=0x%04X\n",avp, avp->flags); name = get_avp_name(avp); LM_INFO("\t\t\tname=<%.*s>\n",name->len,name->s); LM_INFO("\t\t\tid=<%d>\n",avp->id); get_avp_val( avp, &val); if (avp->flags&AVP_VAL_STR) { LM_INFO("\t\t\tval_str=<%.*s / %d>\n",val.s.len,val.s.s, val.s.len); } else { LM_INFO("\t\t\tval_int=<%d>\n",val.n); } } return 1; }
/** * search first avp begining with 'start->next' * if start==NULL, beging from head of avp list */ struct usr_avp *search_first_avp( unsigned short flags, int id, int_str *val, struct usr_avp *start) { struct usr_avp *head; struct usr_avp *avp; if (id < 0) { LM_ERR("invalid avp id %d\n", id); return 0; } if(start==0) { assert( crt_avps!=0 ); if (*crt_avps==0) return 0; head = *crt_avps; } else { if(start->next==0) return 0; head = start->next; } /* search for the AVP by ID (&name) */ avp = internal_search_ID_avp(head, id, flags&AVP_SCRIPT_MASK); /* get the value - if required */ if (avp && val) get_avp_val(avp, val); return avp; }
/* * Report originate call setup usage */ void ospReportOrigSetupUsage(void) { osp_dest* dest = NULL; osp_dest* lastused = NULL; struct usr_avp* destavp = NULL; int_str destval; OSPTTRANHANDLE transaction = -1; int lastcode = 0; int errorcode; struct search_state st; errorcode = OSPPTransactionNew(_osp_provider, &transaction); 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, 0)) { get_avp_val(destavp, &destval); /* OSP destination is wrapped in a string */ dest = (osp_dest*)destval.s.s; if (dest->used == 1) { if (dest->reported == 1) { LM_DBG("orig setup already reported\n"); break; } else { dest->reported = 1; } LM_DBG("iterating through used destination\n"); ospDumpDestination(dest); lastused = dest; errorcode = ospBuildUsageFromDestination(transaction, dest, lastcode); 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); 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); } }
struct usr_avp *search_next_avp( struct usr_avp *avp, int_str *val ) { if (avp==0 || avp->next==0) return 0; avp = internal_search_ID_avp( avp->next, avp->id, avp->flags&AVP_SCRIPT_MASK ); if (avp && val) get_avp_val(avp, val); return avp; }
struct usr_avp *clone_avp_list(struct usr_avp *old) { struct usr_avp *a; int_str val; if (!old) return NULL; /* create a copy of the old AVP */ get_avp_val( old, &val ); a = new_avp( old->flags, old->id, val); if (a==NULL) { LM_ERR("cloning failed, trunking the list\n"); return NULL; } a->next = clone_avp_list(old->next); return a; }
/** * search first avp begining with 'start->next' * if start==NULL, beging from head of avp list */ struct usr_avp *search_first_avp( unsigned short flags, int_str name, int_str *val, struct usr_avp *start) { struct usr_avp *head; struct usr_avp *avp; if(start==0) { assert( crt_avps!=0 ); if (*crt_avps==0) return 0; head = *crt_avps; } else { if(start->next==0) return 0; head = start->next; } if ( name.n==0) { LM_ERR("0 ID or NULL NAME AVP!\n"); return 0; } /* search for the AVP by ID (&name) */ if (flags&AVP_NAME_STR) { if ( name.s.s==0 || name.s.len==0) { LM_ERR("empty avp name!\n"); return 0; } avp = internal_search_name_avp(head,compute_ID(&name.s),&name.s, flags&AVP_SCRIPT_MASK); } else { avp = internal_search_ID_avp(head, name.n, flags&AVP_SCRIPT_MASK); } /* get the value - if required */ if (avp && val) get_avp_val(avp, val); return avp; }
/* * 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; }
static inline avp_t *avp_dup(avp_t *avp) { avp_value_t val; avp_name_t name; str *s; if (avp) { get_avp_val(avp, &val); 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; return create_avp(avp->flags, name, val); } return NULL; }
/* * 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 int restore_reg_avps(struct ucontact *info) { avp_t *avp; avp_value_t val; avp_name_t name; str *s; /* remove all these AVPs ? */ avp = info->avps; while (avp) { remove_avps(avp); avp = avp->next; } /* add stored AVPs */ avp = info->avps; while (avp) { get_avp_val(avp, &val); 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; /* trace_avp("restoring avp", avp); */ /* modify flags here? */ add_avp(avp->flags, name, val); avp = avp->next; } return 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); }
/* * 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"); } }
/* * sends avp list to log in readable form * */ static void dump_avp_reverse(avp_t* avp) { str* name; int_str val; if (avp) { /* AVPs are added to front of the list, reverse by recursion */ dump_avp_reverse(avp->next); name=get_avp_name(avp); get_avp_val(avp, &val); switch(avp->flags&(AVP_NAME_STR|AVP_VAL_STR)) { case 0: /* avp type ID, int value */ LOG(L_INFO,"AVP[%d]=%d\n", avp->id, val.n); break; case AVP_NAME_STR: /* avp type str, int value */ name=get_avp_name(avp); LOG(L_INFO,"AVP[\"%.*s\"]=%d\n", name->len, name->s, val.n); break; case AVP_VAL_STR: /* avp type ID, str value */ LOG(L_INFO,"AVP[%d]=\"%.*s\"\n", avp->id, val.s.len, val.s.s); break; case AVP_NAME_STR|AVP_VAL_STR: /* avp type str, str value */ name=get_avp_name(avp); LOG(L_INFO,"AVP[\"%.*s\"]=\"%.*s\"\n", name->len, name->s, val.s.len, val.s.s); break; } } }
/* * 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; }
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); } }
static int request_hf_helper(struct sip_msg* msg, str* hf, avp_ident_t* ident, struct lump* anchor, struct search_state* st, int front, int reverse, int reply) { struct lump* new_anchor; static struct search_state state; avp_t* avp; char* s; str fin_val; int len, ret; int_str val; struct hdr_field* pos, *found = NULL; if (!anchor && !reply) { if (parse_headers(msg, HDR_EOH_F, 0) == -1) { LOG(L_ERR, "ERROR: request_hf_helper: Error while parsing message\n"); return -1; } pos = msg->headers; while (pos && (pos->type != HDR_EOH_T)) { if ((hf->len == pos->name.len) && (!strncasecmp(hf->s, pos->name.s, pos->name.len))) { found = pos; if (front) { break; } } pos = pos->next; } if (found) { if (front) { len = found->name.s - msg->buf; } else { len = found->name.s + found->len - msg->buf; } } else { len = msg->unparsed - msg->buf; } new_anchor = anchor_lump(msg, len, 0, 0); if (new_anchor == 0) { LOG(L_ERR, "ERROR: request_hf_helper: Can't get anchor\n"); return -1; } } else { new_anchor = anchor; } if (!st) { st = &state; avp = search_avp(*ident, NULL, st); ret = -1; } else { avp = search_next_avp(st, NULL); ret = 1; } if (avp) { if (reverse && (request_hf_helper(msg, hf, ident, new_anchor, st, front, reverse, reply) == -1)) { return -1; } get_avp_val(avp, &val); if (avp->flags & AVP_VAL_STR) { fin_val = val.s; } else { fin_val.s = int2str(val.n, &fin_val.len); } len = hf->len + 2 + fin_val.len + 2; s = (char*)pkg_malloc(len); if (!s) { LOG(L_ERR, "ERROR: request_hf_helper: No memory left for data lump\n"); return -1; } memcpy(s, hf->s, hf->len); memcpy(s + hf->len, ": ", 2 ); memcpy(s + hf->len+2, fin_val.s, fin_val.len ); memcpy(s + hf->len + 2 + fin_val.len, CRLF, CRLF_LEN); if (reply) { if (add_lump_rpl( msg, s, len, LUMP_RPL_HDR | LUMP_RPL_NODUP) == 0) { LOG(L_ERR, "ERROR: request_hf_helper: Can't insert RPL lump\n"); pkg_free(s); return -1; } } else { if ((front && (insert_new_lump_before(new_anchor, s, len, 0) == 0)) || (!front && (insert_new_lump_after(new_anchor, s, len, 0) == 0))) { LOG(L_ERR, "ERROR: request_hf_helper: Can't insert lump\n"); pkg_free(s); return -1; } } if (!reverse && (request_hf_helper(msg, hf, ident, new_anchor, st, front, reverse, reply) == -1)) { return -1; } return 1; }; /* in case of topmost call (st==NULL) return error */ /* otherwise it's OK, no more AVPs found */ return ret; }
int ops_dbstore_avps (struct sip_msg* msg, struct fis_param *sp, struct db_param *dbp, struct db_url *url, int use_domain) { struct sip_uri uri; struct usr_avp **avp_list; struct usr_avp *avp; unsigned short name_type; int avp_name; int_str i_s; str uuid; int keys_nr; int n; pv_value_t xvalue; str *s0, *s1, *s2; str *sn; s0 = s1 = s2 = NULL; name_type = 0; if (!((sp->opd&AVPOPS_VAL_PVAR)||(sp->opd&AVPOPS_VAL_STR))) { LM_CRIT("invalid flag combination (%d/%d)\n", sp->opd, sp->ops); goto error; } keys_nr = 6; /* uuid, avp name, avp val, avp type, user, domain */ /* get uuid from avp */ if (sp->opd&AVPOPS_VAL_PVAR) { if(pv_get_spec_value(msg, &(sp->u.sval), &xvalue)!=0) { LM_CRIT("failed to get PVAR value (%d/%d)\n", sp->opd, sp->ops); goto error; } if(xvalue.flags&(PV_VAL_NULL|PV_VAL_EMPTY)) { LM_ERR("no value for first param\n"); goto error; } uuid = xvalue.rs; } else { uuid.s = sp->u.s.s; uuid.len = sp->u.s.len; } if(sp->opd&AVPOPS_FLAG_UUID0) { s0 = &uuid; } else { /* parse uri */ if (parse_uri(uuid.s, uuid.len, &uri)<0) { LM_ERR("failed to parse uri\n"); goto error; } /* check uri */ if(!uri.user.s|| !uri.user.len|| !uri.host.len|| !uri.host.s) { LM_ERR("incomplet uri <%.*s>\n", uuid.len, uuid.s); goto error; } if((sp->opd&AVPOPS_FLAG_URI0)||(sp->opd&AVPOPS_FLAG_USER0)) s1 = &uri.user; if((sp->opd&AVPOPS_FLAG_URI0)||(sp->opd&AVPOPS_FLAG_DOMAIN0)) s2 = &uri.host; } /* set values for keys */ store_vals[0].val.str_val = (s0)?*s0:empty; store_vals[4].val.str_val = (s1)?*s1:empty; if (use_domain || sp->opd&AVPOPS_FLAG_DOMAIN0) store_vals[5].val.str_val = (s2)?*s2:empty; avp_name = -1; /* is dynamic avp name ? */ if(dbp->a.type==AVPOPS_VAL_PVAR) { if(pv_has_dname(&dbp->a.u.sval)) { /* TODO change here to be aware of the int name */ if(pv_get_spec_name(msg, &(dbp->a.u.sval.pvp), &xvalue)!=0) { LM_CRIT("failed to get value for P2\n"); goto error; } if(xvalue.flags&(PV_VAL_NULL|PV_VAL_EMPTY)) { LM_INFO("no value for P2\n"); goto error; } if(xvalue.flags&PV_TYPE_INT) { name_type = 0; avp_name = xvalue.ri; } else { name_type = AVP_NAME_STR; avp_name = -1; } if(xvalue.flags&PV_VAL_STR) { if(xvalue.rs.len>=AVPOPS_ATTR_LEN) { LM_ERR("name too long [%d/%.*s...]\n", xvalue.rs.len, 16, xvalue.rs.s); goto error; } dbp->sa.s = avpops_attr_buf; memcpy(dbp->sa.s, xvalue.rs.s, xvalue.rs.len); dbp->sa.len = xvalue.rs.len; dbp->sa.s[dbp->sa.len] = '\0'; avp_name = get_avp_id(&dbp->sa); /* search for the id only once */ if (avp_name < 0) { LM_ERR("cannot find avp\n"); goto error; } } else { LM_INFO("no string value for p2\n"); goto error; } } else { name_type = dbp->a.u.sval.pvp.pvn.u.isname.type; avp_name = dbp->a.u.sval.pvp.pvn.u.isname.name.n; } } else { LM_WARN("TODO: avp is not a dynamic name <%.*s> name is %d\n", dbp->sa.len, dbp->sa.s, avp_name); avp_name = -1; } /* set the script flags */ if(dbp->a.type==AVPOPS_VAL_PVAR) name_type |= dbp->a.u.sval.pvp.pvn.u.isname.type&0xff00; /* set uuid/(username and domain) fields */ n =0 ; if ((dbp->a.opd&AVPOPS_VAL_NONE)==0) { /* if avp wasn't found yet */ if (avp_name < 0) { avp_name = get_avp_id(&dbp->sa); /* search for the id only once */ if (avp_name < 0) { LM_ERR("cannot find avp\n"); goto error; } } /* avp name is known ->set it and its type */ store_vals[1].val.str_val = dbp->sa; /*attr name*/ avp = search_first_avp( 0, avp_name, &i_s, 0); for( ; avp; avp=search_first_avp( 0, avp_name, &i_s, avp)) { /* 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( url, store_keys, store_vals, 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; /* set attribute name and type */ if ( (sn=get_avp_name(avp))==0 ) i_s.n = avp->id; else i_s.s = *sn; int_str2db_val( i_s, &store_vals[1].val.str_val, 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( url, store_keys, store_vals, keys_nr, &dbp->table)==0) { avp->flags |= AVP_IS_IN_DB; n++; } } } LM_DBG(" %d avps were stored\n",n); return n==0?-1:1; error: return -1; }
/* * 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; }
/* * 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; }