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; }
int do_lb_is_started(struct sip_msg *req) { struct usr_avp *group_avp; struct usr_avp *mask_avp; struct usr_avp *res_avp; return ( ((group_avp=search_first_avp(0, group_avp_name, NULL, NULL))!=NULL) && (is_avp_str_val(group_avp) == 0) && ((mask_avp =search_first_avp(0, mask_avp_name, NULL, NULL))!=NULL) && (is_avp_str_val(mask_avp) != 0) && ((res_avp =search_first_avp(0, res_avp_name, NULL, NULL))!=NULL) && (is_avp_str_val(res_avp) != 0) ) ? 1 : -1; }
int do_lb_disable_dst(struct sip_msg *req, struct lb_data *data, unsigned int verbose) { struct usr_avp *id_avp; int_str id_val; struct lb_dst *dst; int old_flags; id_avp = search_first_avp( 0, id_avp_name, &id_val, NULL); if( id_avp && (is_avp_str_val(id_avp) == 0) ) { for( dst=data->dsts ; dst ; dst=dst->next ) { if( dst->id == id_val.n ) { old_flags = dst->flags; dst->flags |= LB_DST_STAT_DSBL_FLAG; if( dst->flags != old_flags ) { lb_raise_event(dst); if( verbose ) LM_INFO("manually disable destination %d <%.*s> " "from script\n",dst->id, dst->uri.len, dst->uri.s); } return 0; } } } else LM_DBG("no AVP ID -> nothing to disable\n"); return -1; }
/*! \brief the is_registered() function * Return true if the AOR in the Request-URI is registered, * it is similar to lookup but registered neither rewrites * the Request-URI nor appends branches */ int registered(struct sip_msg* _m, udomain_t* _d, str* _uri) { str uri, aor; urecord_t* r; ucontact_t* ptr; int res; int_str match_callid=(int_str)0; if(_uri!=NULL) { uri = *_uri; } else { if (_m->new_uri.s) uri = _m->new_uri; else uri = _m->first_line.u.request.uri; } if (extract_aor(&uri, &aor, NULL) < 0) { LM_ERR("failed to extract address of record\n"); return -1; } ul.lock_udomain(_d, &aor); res = ul.get_urecord(_d, &aor, &r); if (res < 0) { ul.unlock_udomain(_d, &aor); LM_ERR("failed to query usrloc\n"); return -1; } if (res == 0) { if (reg_callid_avp_name.n) { struct usr_avp *avp = search_first_avp( reg_callid_avp_type, reg_callid_avp_name, &match_callid, 0); if (!(avp && is_avp_str_val(avp))) match_callid.n = 0; match_callid.s.s = NULL; } else { match_callid.n = 0; match_callid.s.s = NULL; } for (ptr = r->contacts; ptr; ptr = ptr->next) { if(!VALID_CONTACT(ptr, act_time)) continue; if (match_callid.s.s && /* optionally enforce tighter matching w/ Call-ID */ memcmp(match_callid.s.s,ptr->callid.s,match_callid.s.len)) continue; ul.release_urecord(r); ul.unlock_udomain(_d, &aor); LM_DBG("'%.*s' found in usrloc\n", aor.len, ZSW(aor.s)); return 1; } } ul.unlock_udomain(_d, &aor); LM_DBG("'%.*s' not found in usrloc\n", aor.len, ZSW(aor.s)); return -1; }
int nio_msg_received(void *data) { sip_msg_t msg; str *obuf; char *nbuf = NULL; int_str avp_value; struct usr_avp *avp; struct run_act_ctx ra_ctx; obuf = (str*)data; if (obuf->len < nio_min_msg_len) { return -1; } memset(&msg, 0, sizeof(sip_msg_t)); msg.buf = obuf->s; msg.len = obuf->len; nio_is_incoming = 1; init_run_actions_ctx(&ra_ctx); run_actions(&ra_ctx, event_rt.rlist[nio_route_no], &msg); if(nio_msg_avp_name.n!=0) { avp = NULL; avp=search_first_avp(nio_msg_avp_type, nio_msg_avp_name, &avp_value, 0); if(avp!=NULL && is_avp_str_val(avp)) { msg.buf = avp_value.s.s; msg.len = avp_value.s.len; nbuf = nio_msg_update(&msg, (unsigned int*)&obuf->len); if(obuf->len>=BUF_SIZE) { LM_ERR("new buffer overflow (%d)\n", obuf->len); pkg_free(nbuf); return -1; } memcpy(obuf->s, nbuf, obuf->len); obuf->s[obuf->len] = '\0'; } else { LM_WARN("no value set for AVP %.*s, using unmodified message\n", nio_msg_avp_param.len, nio_msg_avp_param.s); } } if(nbuf!=NULL) pkg_free(nbuf); free_sip_msg(&msg); return 0; }
static inline str* siptrace_get_table(void) { static int_str avp_value; struct usr_avp *avp; if(trace_table_avp < 0) return &siptrace_table; avp=search_first_avp(trace_table_avp_type, trace_table_avp, &avp_value, 0); if(avp==NULL || !is_avp_str_val(avp) || avp_value.s.len<=0) return &siptrace_table; return &avp_value.s; }
int nio_msg_sent(void *data) { sip_msg_t msg; str *obuf; int_str avp_value; struct usr_avp *avp; struct run_act_ctx ra_ctx; obuf = (str*)data; if (obuf->len < nio_min_msg_len) { return -1; } memset(&msg, 0, sizeof(sip_msg_t)); msg.buf = obuf->s; msg.len = obuf->len; nio_is_incoming = 0; init_run_actions_ctx(&ra_ctx); run_actions(&ra_ctx, event_rt.rlist[nio_route_no], &msg); if(nio_msg_avp_name.n!=0) { avp = NULL; avp=search_first_avp(nio_msg_avp_type, nio_msg_avp_name, &avp_value, 0); if(avp!=NULL && is_avp_str_val(avp)) { msg.buf = avp_value.s.s; msg.len = avp_value.s.len; obuf->s = nio_msg_update(&msg, (unsigned int*)&obuf->len); } else { LM_WARN("no value set for AVP %.*s, using unmodified message\n", nio_msg_avp_param.len, nio_msg_avp_param.s); } } free_sip_msg(&msg); return 0; }
static int l_siplua_AVP_get(lua_State *L) { struct usr_avp *first_avp; int name; str s; int_str val; int flags = 0; luaL_checkany(L, 1); s.s = (char *) lua_tostring(L, 1); s.len = strlen(s.s); name = get_avp_id(&s); first_avp = search_first_avp(flags, name, &val, NULL); if (first_avp != NULL) { if (is_avp_str_val(first_avp)) lua_pushlstring(L, val.s.s, val.s.len); else lua_pushinteger(L, val.n); } else lua_pushnil(L); return 1; }
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; }
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; }
/*! \brief * Extract Address of Record */ int extract_aor(str* _uri, str* _a) { static char aor_buf[MAX_AOR_LEN]; str tmp; struct sip_uri puri; int user_len; int_str avp_val; struct usr_avp *avp; str *uri; str realm_prefix; memset(aor_buf, 0, MAX_AOR_LEN); if (aor_avp_name.n != 0) { avp = search_first_avp(aor_avp_type, aor_avp_name, &avp_val, 0); if (avp && is_avp_str_val(avp)) { uri = &avp_val.s; } else { uri = _uri; } } else { uri = _uri; } if (parse_uri(uri->s, uri->len, &puri) < 0) { rerrno = R_AOR_PARSE; LM_ERR("failed to parse Address of Record\n"); return -1; } if ((puri.user.len + puri.host.len + 1 + 4) > MAX_AOR_LEN || puri.user.len > USERNAME_MAX_SIZE || puri.host.len > DOMAIN_MAX_SIZE) { rerrno = R_AOR_LEN; LM_ERR("Address Of Record too long\n"); return -2; } _a->s = aor_buf; _a->len = puri.user.len + 4; strncpy(_a->s, "sip:", 4); str tmps; tmps.s = _a->s + 4; tmps.len = puri.user.len; if (un_escape(&puri.user, &tmps) < 0) { rerrno = R_UNESCAPE; LM_ERR("failed to unescape username\n"); return -3; } user_len = tmps.len + 4;//_a->len; if (user_len>4) aor_buf[_a->len++] = '@'; /* strip prefix (if defined) */ realm_prefix.s = cfg_get(registrar, registrar_cfg, realm_pref); realm_prefix.len = strlen(realm_prefix.s); if (realm_prefix.len && realm_prefix.len < puri.host.len && (memcmp(realm_prefix.s, puri.host.s, realm_prefix.len) == 0)) { memcpy(aor_buf + _a->len, puri.host.s + realm_prefix.len, puri.host.len - realm_prefix.len); _a->len += puri.host.len - realm_prefix.len; } else { memcpy(aor_buf + _a->len, puri.host.s, puri.host.len); _a->len += puri.host.len; } if (cfg_get(registrar, registrar_cfg, case_sensitive) && user_len) { tmp.s = _a->s + user_len + 1; tmp.len = _a->s + _a->len - tmp.s; strlower(&tmp); } else { strlower(_a); } return 0; }
int ops_subst(struct sip_msg* msg, struct fis_param** src, struct subst_expr* se) { struct usr_avp *avp; struct usr_avp *prev_avp; int_str avp_val; unsigned short name_type1; unsigned short name_type2; int avp_name1; int avp_name2; int n; int nmatches; str* result; n = 0; prev_avp = 0; /* avp name is known ->search by name */ /* get src avp name */ if(avpops_get_aname(msg, src[0], &avp_name1, &name_type1)!=0) { LM_ERR("failed to get src AVP name\n"); return -1; } avp = search_first_avp(name_type1, avp_name1, &avp_val, 0); if(avp==NULL) return -1; if(src[1]!=0) { /* get dst avp name */ if(avpops_get_aname(msg, src[1], &avp_name2, &name_type2)!=0) { LM_ERR("failed to get dst AVP name\n"); return -1; } } else { name_type2 = name_type1; avp_name2 = avp_name1; } /* TODO: delete? if(name_type2&AVP_NAME_STR) { if(avp_name2.s.len>=STR_BUF_SIZE) { LM_ERR("dst name too long\n"); goto error; } strncpy(str_buf, avp_name2.s.s, avp_name2.s.len); str_buf[avp_name2.s.len] = '\0'; avp_name2.s.s = str_buf; } */ while(avp) { if(!is_avp_str_val(avp)) { prev_avp = avp; avp = search_first_avp(name_type1, avp_name1, &avp_val, prev_avp); continue; } result=subst_str(avp_val.s.s, msg, se, &nmatches); if(result!=NULL) { /* build a new avp with new name */ avp_val.s = *result; if(add_avp(name_type2|AVP_VAL_STR, avp_name2, avp_val)==-1 ) { LM_ERR("failed to create new avp\n"); if(result->s!=0) pkg_free(result->s); pkg_free(result); goto error; } if(result->s!=0) pkg_free(result->s); pkg_free(result); n++; /* copy all avps? */ if (!(src[0]->ops&AVPOPS_FLAG_ALL) ) { /* delete the old one? */ if (src[0]->ops&AVPOPS_FLAG_DELETE || src[1]==0) destroy_avp(avp); break; } else { prev_avp = avp; avp = search_first_avp(name_type1,avp_name1,&avp_val,prev_avp); /* delete the old one? */ if (src[0]->ops&AVPOPS_FLAG_DELETE || src[1]==0) destroy_avp( prev_avp ); } } else { prev_avp = avp; avp = search_first_avp(name_type1, avp_name1, &avp_val, prev_avp); } } LM_DBG("subst to %d avps\n", n); return n?1:-1; error: return -1; }