int pv_set_spec_value(struct sip_msg* msg, pv_spec_p sp, int op, pv_value_t *value) { if(sp==NULL || !pv_is_w(sp)) return 0; /* no op */ if(pv_alter_context(sp) && is_route_type(LOCAL_ROUTE)) return 0; /* no op */ return sp->setf(msg, &sp->pvp, op, value); }
int uac_reg_lookup(struct sip_msg *msg, str *src, pv_spec_t *dst, int mode) { char b_ruri[MAX_URI_SIZE]; str s_ruri; struct sip_uri puri; reg_uac_t *reg = NULL; pv_value_t val; if(!pv_is_w(dst)) { LM_ERR("dst is not w/\n"); return -1; } if(mode==0) { reg = reg_ht_get_byuuid(src); if(reg==NULL) { LM_DBG("no uuid: %.*s\n", src->len, src->s); return -1; } snprintf(b_ruri, MAX_URI_SIZE, "sip:%.*s@%.*s", reg->l_username.len, reg->l_username.s, reg->l_domain.len, reg->l_domain.s); s_ruri.s = b_ruri; s_ruri.len = strlen(s_ruri.s); } else { if(parse_uri(src->s, src->len, &puri)!=0) { LM_ERR("failed to parse uri\n"); return -2; } reg = reg_ht_get_byuser(&puri.user, (reg_use_domain)?&puri.host:NULL); if(reg==NULL) { LM_DBG("no user: %.*s\n", src->len, src->s); return -1; } snprintf(b_ruri, MAX_URI_SIZE, "%.*s", reg->l_uuid.len, reg->l_uuid.s); s_ruri.s = b_ruri; s_ruri.len = strlen(s_ruri.s); } memset(&val, 0, sizeof(pv_value_t)); val.flags |= PV_VAL_STR; val.rs = s_ruri; if(pv_set_spec_value(msg, dst, 0, &val)!=0) return -1; return 1; }
int pv_printf_fixup(void** param, int param_no) { pv_spec_t *spec=NULL; pv_elem_t *pvmodel=NULL; str tstr; if(param_no==1) { spec = (pv_spec_t*)pkg_malloc(sizeof(pv_spec_t)); if(spec==NULL) { LM_ERR("out of pkg\n"); return -1; } memset(spec, 0, sizeof(pv_spec_t)); tstr.s = (char*)(*param); tstr.len = strlen(tstr.s); if(pv_parse_spec(&tstr, spec)==NULL) { LM_ERR("unknown script variable in first parameter"); pkg_free(spec); return -1; } if(!pv_is_w(spec)) { LM_ERR("read-only script variable in first parameter"); pkg_free(spec); return -1; } *param = spec; } else if(param_no==2) { pvmodel = 0; tstr.s = (char*)(*param); tstr.len = strlen(tstr.s); if(pv_parse_format(&tstr, &pvmodel)<0) { LM_ERR("error in second parameter"); return -1; } *param = pvmodel; } return 0; }
static int l_siplua_pseudoVarSet(lua_State *L) { struct sipapi_object *o; const char *name; str s; pv_spec_t dspec; pv_value_t val; int retval; o = luaL_checkudata(L, 1, "siplua.api"); name = luaL_checkstring(L, 2); if (*name == '$') ++name; s.s = (char *)name; s.len = strlen(name); if (!pv_parse_spec(&s, &dspec)) return luaL_error(L, "error in parsing pvar `%s'", name); if (!pv_is_w(&dspec)) return luaL_error(L, "read only PV in left expression"); luaL_checkany(L, 3); if (lua_type(L, 3) == LUA_TNIL) { val.flags = PV_VAL_NULL; } else if (lua_type(L, 3) == LUA_TNUMBER) { val.ri = luaL_checkinteger(L, 3); val.flags = PV_VAL_INT; } else { val.rs.s = (char *)luaL_checkstring(L, 3); val.rs.len = strlen(val.rs.s); val.flags = PV_VAL_STR; } /* siplua_log(L_ALERT, "dspec.setf(, , EQ_T, %.*s)", val.rs.len, val.rs.s); */ retval = pv_set_value(o->msg, &dspec, EQ_T, &val); if (retval >= 0) lua_pushboolean(L, 1); else lua_pushnil(L); return 1; }
/* ret= 0! if action -> end of list(e.g DROP), > 0 to continue processing next actions and <0 on error */ int do_action(struct action* a, struct sip_msg* msg) { int ret; int v; int sec,usec; union sockaddr_union* to; struct proxy_l* p; char* tmp; char *new_uri, *end, *crt; int len,i; int user = 0; int expires = 0; str vals[5]; str result; struct sip_uri uri, next_hop; struct sip_uri *u; unsigned short port; int cmatch; struct action *aitem; struct action *adefault; pv_spec_t *spec; pv_elem_p model; pv_value_t val; pv_elem_t *pve; str name_s; struct timeval start; int end_time; action_elem_t *route_params_bak; int route_params_number_bak; /* reset the value of error to E_UNSPEC so avoid unknowledgable functions to return with error (status<0) and not setting it leaving there previous error; cache the previous value though for functions which want to process it */ prev_ser_error=ser_error; ser_error=E_UNSPEC; start_expire_timer(start,execmsgthreshold); ret=E_BUG; switch ((unsigned char)a->type){ case DROP_T: script_trace("core", "drop", msg, a->line) ; action_flags |= ACT_FL_DROP; case EXIT_T: script_trace("core", "exit", msg, a->line) ; ret=0; action_flags |= ACT_FL_EXIT; break; case RETURN_T: script_trace("core", "return", msg, a->line) ; if (a->elem[0].type == SCRIPTVAR_ST) { spec = (pv_spec_t*)a->elem[0].u.data; if(pv_get_spec_value(msg, spec, &val)!=0 || (val.flags&PV_VAL_NULL)) { ret=-1; } else { if(!(val.flags&PV_VAL_INT)) ret = 1; else ret = val.ri; } pv_value_destroy(&val); } else { ret=a->elem[0].u.number; } action_flags |= ACT_FL_RETURN; break; case FORWARD_T: script_trace("core", "forward", msg, a->line) ; if (a->elem[0].type==NOSUBTYPE){ /* parse uri and build a proxy */ if (msg->dst_uri.len) { ret = parse_uri(msg->dst_uri.s, msg->dst_uri.len, &next_hop); u = &next_hop; } else { ret = parse_sip_msg_uri(msg); u = &msg->parsed_uri; } if (ret<0) { LM_ERR("forward: bad_uri dropping packet\n"); break; } /* create a temporary proxy*/ p=mk_proxy(u->maddr_val.len?&u->maddr_val:&u->host, u->port_no, u->proto, (u->type==SIPS_URI_T)?1:0 ); if (p==0){ LM_ERR("bad host name in uri, dropping packet\n"); ret=E_BAD_ADDRESS; goto error_fwd_uri; } ret=forward_request(msg, p); free_proxy(p); /* frees only p content, not p itself */ pkg_free(p); if (ret==0) ret=1; }else if ((a->elem[0].type==PROXY_ST)) { ret=forward_request(msg,(struct proxy_l*)a->elem[0].u.data); if (ret==0) ret=1; }else{ LM_ALERT("BUG in forward() types %d, %d\n", a->elem[0].type, a->elem[1].type); ret=E_BUG; } break; case SEND_T: script_trace("core", "send", msg, a->line) ; if (a->elem[0].type!= PROXY_ST){ LM_ALERT("BUG in send() type %d\n", a->elem[0].type); ret=E_BUG; break; } if (a->elem[1].u.data) { if (a->elem[1].type != SCRIPTVAR_ELEM_ST){ LM_ALERT("BUG in send() header type %d\n",a->elem[1].type); ret=E_BUG; break; } else { pve = (pv_elem_t *)a->elem[1].u.data; } } else { pve = NULL; } to=(union sockaddr_union*) pkg_malloc(sizeof(union sockaddr_union)); if (to==0){ LM_ERR("memory allocation failure\n"); ret=E_OUT_OF_MEM; break; } p=(struct proxy_l*)a->elem[0].u.data; ret=hostent2su(to, &p->host, p->addr_idx, (p->port)?p->port:SIP_PORT ); if (ret==0){ if (pve) { if ( pv_printf_s(msg, pve, &name_s)!=0 || name_s.len == 0 || name_s.s == NULL) { LM_WARN("cannot get string for value\n"); ret=E_UNSPEC; break; } /* build new msg */ tmp = pkg_malloc(msg->len + name_s.len); if (!tmp) { LM_ERR("memory allocation failure\n"); ret = E_OUT_OF_MEM; break; } LM_DBG("searching for first line %d\n", msg->first_line.len); /* search first line of previous msg */ /* copy headers */ len = msg->first_line.len; memcpy(tmp, msg->buf, len); memcpy(tmp + len, name_s.s, name_s.len); memcpy(tmp + len + name_s.len, msg->buf + len, msg->len - len); ret = msg_send(0/*send_sock*/, p->proto, to, 0/*id*/, tmp, msg->len + name_s.len); pkg_free(tmp); } else { ret = msg_send(0/*send_sock*/, p->proto, to, 0/*id*/, msg->buf, msg->len); } if (ret!=0 && p->host.h_addr_list[p->addr_idx+1]) p->addr_idx++; } pkg_free(to); if (ret==0) ret=1; break; case LOG_T: script_trace("core", "log", msg, a->line) ; if ((a->elem[0].type!=NUMBER_ST)|(a->elem[1].type!=STRING_ST)){ LM_ALERT("BUG in log() types %d, %d\n", a->elem[0].type, a->elem[1].type); ret=E_BUG; break; } LM_GEN1(a->elem[0].u.number, "%s", a->elem[1].u.string); ret=1; break; case APPEND_BRANCH_T: script_trace("core", "append_branch", msg, a->line) ; if ((a->elem[0].type!=STR_ST)) { LM_ALERT("BUG in append_branch %d\n", a->elem[0].type ); ret=E_BUG; break; } if (a->elem[0].u.s.s==NULL) { ret = append_branch(msg, 0, &msg->dst_uri, &msg->path_vec, get_ruri_q(), getb0flags(), msg->force_send_socket); /* reset all branch info */ msg->force_send_socket = 0; setb0flags(0); set_ruri_q(Q_UNSPECIFIED); if(msg->dst_uri.s!=0) pkg_free(msg->dst_uri.s); msg->dst_uri.s = 0; msg->dst_uri.len = 0; if(msg->path_vec.s!=0) pkg_free(msg->path_vec.s); msg->path_vec.s = 0; msg->path_vec.len = 0; } else { ret = append_branch(msg, &a->elem[0].u.s, &msg->dst_uri, &msg->path_vec, a->elem[1].u.number, getb0flags(), msg->force_send_socket); } break; case REMOVE_BRANCH_T: script_trace("core", "remove_branch", msg, a->line) ; if (a->elem[0].type == SCRIPTVAR_ST) { spec = (pv_spec_t*)a->elem[0].u.data; if( pv_get_spec_value(msg, spec, &val)!=0 || (val.flags&PV_VAL_NULL) || !(val.flags&PV_VAL_INT) ) { ret=-1; break; } i = val.ri; } else { i=a->elem[0].u.number; } ret = (remove_branch((unsigned int)i)==0)?1:-1; break; case LEN_GT_T: script_trace("core", "len_gt", msg, a->line) ; if (a->elem[0].type!=NUMBER_ST) { LM_ALERT("BUG in len_gt type %d\n", a->elem[0].type ); ret=E_BUG; break; } ret = (msg->len >= (unsigned int)a->elem[0].u.number) ? 1 : -1; break; case SET_DEBUG_T: script_trace("core", "set_debug", msg, a->line) ; if (a->elem[0].type==NUMBER_ST) set_proc_debug_level(a->elem[0].u.number); else reset_proc_debug_level(); ret = 1; break; case SETFLAG_T: script_trace("core", "setflag", msg, a->line) ; ret = setflag( msg, a->elem[0].u.number ); break; case RESETFLAG_T: script_trace("core", "resetflag", msg, a->line) ; ret = resetflag( msg, a->elem[0].u.number ); break; case ISFLAGSET_T: script_trace("core", "isflagset", msg, a->line) ; ret = isflagset( msg, a->elem[0].u.number ); break; case SETSFLAG_T: script_trace("core", "setsflag", msg, a->line) ; ret = setsflag( a->elem[0].u.number ); break; case RESETSFLAG_T: script_trace("core", "resetsflag", msg, a->line) ; ret = resetsflag( a->elem[0].u.number ); break; case ISSFLAGSET_T: script_trace("core", "issflagset", msg, a->line) ; ret = issflagset( a->elem[0].u.number ); break; case SETBFLAG_T: script_trace("core", "setbflag", msg, a->line) ; ret = setbflag( a->elem[0].u.number, a->elem[1].u.number ); break; case RESETBFLAG_T: script_trace("core", "resetbflag", msg, a->line) ; ret = resetbflag( a->elem[0].u.number, a->elem[1].u.number ); break; case ISBFLAGSET_T: script_trace("core", "isbflagset", msg, a->line) ; ret = isbflagset( a->elem[0].u.number, a->elem[1].u.number ); break; case ERROR_T: script_trace("core", "error", msg, a->line) ; if ((a->elem[0].type!=STRING_ST)|(a->elem[1].type!=STRING_ST)){ LM_ALERT("BUG in error() types %d, %d\n", a->elem[0].type, a->elem[1].type); ret=E_BUG; break; } LM_ERR("error(\"%s\", \"%s\") not implemented yet\n", a->elem[0].u.string, a->elem[1].u.string); ret=1; break; case ROUTE_T: script_trace("route", rlist[a->elem[0].u.number].name, msg, a->line) ; if (a->elem[0].type!=NUMBER_ST){ LM_ALERT("BUG in route() type %d\n", a->elem[0].type); ret=E_BUG; break; } if ((a->elem[0].u.number>RT_NO)||(a->elem[0].u.number<0)){ LM_ALERT("BUG - invalid routing table number in" "route(%lu)\n", a->elem[0].u.number); ret=E_CFG; break; } /* check if the route has parameters */ if (a->elem[1].type != 0) { if (a->elem[1].type != NUMBER_ST || a->elem[2].type != SCRIPTVAR_ELEM_ST) { LM_ALERT("BUG in route() type %d/%d\n", a->elem[1].type, a->elem[2].type); ret=E_BUG; break; } route_params_bak = route_params; route_params = (action_elem_t *)a->elem[2].u.data; route_params_number_bak = route_params_number; route_params_number = a->elem[1].u.number; return_code=run_actions(rlist[a->elem[0].u.number].a, msg); route_params = route_params_bak; route_params_number = route_params_number_bak; } else { return_code=run_actions(rlist[a->elem[0].u.number].a, msg); } ret=return_code; break; case REVERT_URI_T: script_trace("core", "revert_uri", msg, a->line) ; if (msg->new_uri.s) { pkg_free(msg->new_uri.s); msg->new_uri.len=0; msg->new_uri.s=0; msg->parsed_uri_ok=0; /* invalidate current parsed uri*/ }; ret=1; break; case SET_HOST_T: case SET_HOSTPORT_T: case SET_USER_T: case SET_USERPASS_T: case SET_PORT_T: case SET_URI_T: case PREFIX_T: case STRIP_T: case STRIP_TAIL_T: script_trace("core", (unsigned char)a->type == SET_HOST_T ? "set_host" : (unsigned char)a->type == SET_HOSTPORT_T ? "set_hostport" : (unsigned char)a->type == SET_USER_T ? "set_user" : (unsigned char)a->type == SET_USERPASS_T ? "set_userpass" : (unsigned char)a->type == SET_PORT_T ? "set_port" : (unsigned char)a->type == SET_URI_T ? "set_uri" : (unsigned char)a->type == PREFIX_T ? "prefix" : (unsigned char)a->type == STRIP_T ? "strip" : "strip_tail", msg, a->line); user=0; if (a->type==STRIP_T || a->type==STRIP_TAIL_T) { if (a->elem[0].type!=NUMBER_ST) { LM_ALERT("BUG in set*() type %d\n", a->elem[0].type); break; } } else if (a->elem[0].type!=STR_ST){ LM_ALERT("BUG in set*() type %d\n", a->elem[0].type); ret=E_BUG; break; } if (a->type==SET_URI_T) { if (set_ruri( msg, &a->elem[0].u.s) ) { LM_ERR("failed to set new RURI\n"); ret=E_OUT_OF_MEM; break; } ret=1; break; } if (msg->new_uri.s) { tmp=msg->new_uri.s; len=msg->new_uri.len; }else{ tmp=msg->first_line.u.request.uri.s; len=msg->first_line.u.request.uri.len; } if (parse_uri(tmp, len, &uri)<0){ LM_ERR("bad uri <%.*s>, dropping packet\n", len, tmp); ret=E_UNSPEC; break; } new_uri=pkg_malloc(MAX_URI_SIZE); if (new_uri==0){ LM_ERR("memory allocation failure\n"); ret=E_OUT_OF_MEM; break; } end=new_uri+MAX_URI_SIZE; crt=new_uri; /* begin copying */ len = (uri.user.len?uri.user.s:uri.host.s) - tmp; if (crt+len>end) goto error_uri; memcpy(crt,tmp,len);crt+=len; if (a->type==PREFIX_T) { if (crt+a->elem[0].u.s.len>end) goto error_uri; memcpy( crt, a->elem[0].u.s.s, a->elem[0].u.s.len); crt+=a->elem[0].u.s.len; /* whatever we had before, with prefix we have username now */ user=1; } if ((a->type==SET_USER_T)||(a->type==SET_USERPASS_T)) { tmp=a->elem[0].u.s.s; len=a->elem[0].u.s.len; } else if (a->type==STRIP_T) { if (a->elem[0].u.number>uri.user.len) { LM_WARN("too long strip asked; " " deleting username: %lu of <%.*s>\n", a->elem[0].u.number, uri.user.len, uri.user.s); len=0; } else if (a->elem[0].u.number==uri.user.len) { len=0; } else { tmp=uri.user.s + a->elem[0].u.number; len=uri.user.len - a->elem[0].u.number; } } else if (a->type==STRIP_TAIL_T) { if (a->elem[0].u.number>uri.user.len) { LM_WARN("too long strip_tail asked;" " deleting username: %lu of <%.*s>\n", a->elem[0].u.number, uri.user.len, uri.user.s); len=0; } else if (a->elem[0].u.number==uri.user.len) { len=0; } else { tmp=uri.user.s; len=uri.user.len - a->elem[0].u.number; } } else { tmp=uri.user.s; len=uri.user.len; } if (len){ if(crt+len>end) goto error_uri; memcpy(crt,tmp,len);crt+=len; user=1; /* we have an user field so mark it */ } if (a->type==SET_USERPASS_T) tmp=0; else tmp=uri.passwd.s; /* passwd */ if (tmp){ len=uri.passwd.len; if(crt+len+1>end) goto error_uri; *crt=':'; crt++; memcpy(crt,tmp,len);crt+=len; } /* host */ if (user || tmp){ /* add @ */ if(crt+1>end) goto error_uri; *crt='@'; crt++; } if ((a->type==SET_HOST_T) ||(a->type==SET_HOSTPORT_T)) { tmp=a->elem[0].u.s.s; len=a->elem[0].u.s.len; } else { tmp=uri.host.s; len = uri.host.len; } if (tmp){ if(crt+len>end) goto error_uri; memcpy(crt,tmp,len);crt+=len; } /* port */ if (a->type==SET_HOSTPORT_T) tmp=0; else if (a->type==SET_PORT_T) { tmp=a->elem[0].u.s.s; len=a->elem[0].u.s.len; } else { tmp=uri.port.s; len = uri.port.len; } if (tmp && len>0){ if(crt+len+1>end) goto error_uri; *crt=':'; crt++; memcpy(crt,tmp,len);crt+=len; } /* params */ tmp=uri.params.s; if (tmp){ /* include in param string the starting ';' */ len=uri.params.len+1; tmp--; if(crt+len+1>end) goto error_uri; /* if a maddr param is present, strip it out */ if (uri.maddr.len && (a->type==SET_HOSTPORT_T || a->type==SET_HOST_T)) { memcpy(crt,tmp,uri.maddr.s-tmp-1); crt+=uri.maddr.s-tmp-1; memcpy(crt,uri.maddr_val.s+uri.maddr_val.len, tmp+len-uri.maddr_val.s-uri.maddr_val.len); crt+=tmp+len-uri.maddr_val.s-uri.maddr_val.len; } else { memcpy(crt,tmp,len);crt+=len; } } /* headers */ tmp=uri.headers.s; if (tmp){ len=uri.headers.len; if(crt+len+1>end) goto error_uri; *crt='?'; crt++; memcpy(crt,tmp,len);crt+=len; } *crt=0; /* null terminate the thing */ /* copy it to the msg */ if (msg->new_uri.s) pkg_free(msg->new_uri.s); msg->new_uri.s=new_uri; msg->new_uri.len=crt-new_uri; msg->parsed_uri_ok=0; ret=1; break; case SET_DSTURI_T: script_trace("core", "set_dsturi", msg, a->line) ; if (a->elem[0].type!=STR_ST){ LM_ALERT("BUG in setdsturi() type %d\n", a->elem[0].type); ret=E_BUG; break; } if(set_dst_uri(msg, &a->elem[0].u.s)!=0) ret = -1; else ret = 1; break; case SET_DSTHOST_T: case SET_DSTPORT_T: script_trace("core", (unsigned char) a->type == SET_DSTHOST_T ? "set_dsturi" : "set_dstport", msg, a->line); if (a->elem[0].type!=STR_ST){ LM_ALERT("BUG in domain setting type %d\n", a->elem[0].type); ret=E_BUG; break; } tmp = msg->dst_uri.s; len = msg->dst_uri.len; if (tmp == NULL || len == 0) { LM_ERR("failure - null uri\n"); ret = E_UNSPEC; break; } if (a->type == SET_DSTHOST_T && (a->elem[0].u.s.s == NULL || a->elem[0].u.s.len == 0)) { LM_ERR("cannot set a null uri domain\n"); break; } if (parse_uri(tmp, len, &uri)<0) { LM_ERR("bad uri <%.*s>, dropping packet\n", len, tmp); break; } new_uri=pkg_malloc(MAX_URI_SIZE); if (new_uri == NULL) { LM_ERR("memory allocation failure\n"); ret=E_OUT_OF_MEM; break; } end=new_uri+MAX_URI_SIZE; crt=new_uri; len = (uri.user.len?uri.user.s:uri.host.s) - tmp; if (crt+len>end) goto error_uri; memcpy(crt,tmp,len); crt += len; /* user */ tmp = uri.user.s; len = uri.user.len; if (tmp) { if (crt+len>end) goto error_uri; memcpy(crt,tmp,len); crt += len; user = 1; } /* passwd */ tmp = uri.passwd.s; len = uri.passwd.len; if (user || tmp) { if (crt+len+1>end) goto error_uri; *crt++=':'; memcpy(crt, tmp, len); crt += len; } /* host */ if (a->type==SET_DSTHOST_T) { tmp = a->elem[0].u.s.s; len = a->elem[0].u.s.len; } else { tmp = uri.host.s; len = uri.host.len; } if (tmp) { if (user) { if (crt+1>end) goto error_uri; *crt++='@'; } if (crt+len+1>end) goto error_uri; memcpy(crt, tmp, len); crt += len; } /* port */ if (a->type==SET_DSTPORT_T) { tmp = a->elem[0].u.s.s; len = a->elem[0].u.s.len; } else { tmp = uri.port.s; len = uri.port.len; } if (tmp) { if (crt+len+1>end) goto error_uri; *crt++=':'; memcpy(crt, tmp, len); crt += len; } /* params */ tmp=uri.params.s; if (tmp){ len=uri.params.len; if(crt+len+1>end) goto error_uri; *crt++=';'; memcpy(crt,tmp,len); crt += len; } /* headers */ tmp=uri.headers.s; if (tmp){ len=uri.headers.len; if(crt+len+1>end) goto error_uri; *crt++='?'; memcpy(crt,tmp,len); crt += len; } *crt=0; /* null terminate the thing */ /* copy it to the msg */ pkg_free(msg->dst_uri.s); msg->dst_uri.s=new_uri; msg->dst_uri.len=crt-new_uri; ret = 1; break; case RESET_DSTURI_T: script_trace("core", "reset_dsturi", msg, a->line) ; if(msg->dst_uri.s!=0) pkg_free(msg->dst_uri.s); msg->dst_uri.s = 0; msg->dst_uri.len = 0; ret = 1; break; case ISDSTURISET_T: script_trace("core", "isdsturiset", msg, a->line) ; if(msg->dst_uri.s==0 || msg->dst_uri.len<=0) ret = -1; else ret = 1; break; case IF_T: script_trace("core", "if", msg, a->line) ; /* if null expr => ignore if? */ if ((a->elem[0].type==EXPR_ST)&&a->elem[0].u.data){ v=eval_expr((struct expr*)a->elem[0].u.data, msg, 0); /* set return code to expr value */ if (v<0 || (action_flags&ACT_FL_RETURN) || (action_flags&ACT_FL_EXIT) ){ if (v==EXPR_DROP || (action_flags&ACT_FL_RETURN) || (action_flags&ACT_FL_EXIT) ){ /* hack to quit on DROP*/ ret=0; return_code = 0; break; }else{ LM_WARN("error in expression (l=%d)\n", a->line); } } ret=1; /*default is continue */ if (v>0) { if ((a->elem[1].type==ACTIONS_ST)&&a->elem[1].u.data){ ret=run_action_list( (struct action*)a->elem[1].u.data,msg ); return_code = ret; } else return_code = v; }else{ if ((a->elem[2].type==ACTIONS_ST)&&a->elem[2].u.data){ ret=run_action_list( (struct action*)a->elem[2].u.data,msg); return_code = ret; } else return_code = v; } } break; case WHILE_T: script_trace("core", "while", msg, a->line) ; /* if null expr => ignore if? */ if ((a->elem[0].type==EXPR_ST)&&a->elem[0].u.data){ len = 0; while(1) { if(len++ >= max_while_loops) { LM_INFO("max while loops are encountered\n"); break; } v=eval_expr((struct expr*)a->elem[0].u.data, msg, 0); /* set return code to expr value */ if (v<0 || (action_flags&ACT_FL_RETURN) || (action_flags&ACT_FL_EXIT) ){ if (v==EXPR_DROP || (action_flags&ACT_FL_RETURN) || (action_flags&ACT_FL_EXIT) ){ ret=0; return_code = 0; break; }else{ LM_WARN("error in expression (l=%d)\n", a->line); } } ret=1; /*default is continue */ if (v>0) { if ((a->elem[1].type==ACTIONS_ST) &&a->elem[1].u.data){ ret=run_action_list( (struct action*)a->elem[1].u.data,msg ); /* check if return was done */ if ((action_flags&ACT_FL_RETURN) || (action_flags&ACT_FL_EXIT) ){ break; } return_code = ret; } else { /* we should not get here */ return_code = v; break; } } else { /* condition was false */ return_code = v; break; } } } break; case CACHE_STORE_T: script_trace("core", "cache_store", msg, a->line) ; if ((a->elem[0].type!=STR_ST)) { LM_ALERT("BUG in cache_store() - first argument not of" " type string [%d]\n", a->elem[0].type ); ret=E_BUG; break; } if ((a->elem[1].type!=STR_ST)) { LM_ALERT("BUG in cache_store() - second argument not of " "type string [%d]\n", a->elem[1].type ); ret=E_BUG; break; } if ((a->elem[2].type!=STR_ST)) { LM_ALERT("BUG in cache_store() - third argument not of type" " string%d\n", a->elem[2].type ); ret=E_BUG; break; } str val_s; /* parse the name argument */ pve = (pv_elem_t *)a->elem[1].u.data; if ( pv_printf_s(msg, pve, &name_s)!=0 || name_s.len == 0 || name_s.s == NULL) { LM_WARN("cannot get string for value\n"); ret=E_BUG; break; } /* parse the value argument */ pve = (pv_elem_t *)a->elem[2].u.data; if ( pv_printf_s(msg, pve, &val_s)!=0 || val_s.len == 0 || val_s.s == NULL) { LM_WARN("cannot get string for value\n"); ret=E_BUG; break; } /* get the expires value */ if ( a->elem[3].type == SCRIPTVAR_ST ) { spec = (pv_spec_t*)a->elem[3].u.data; memset(&val, 0, sizeof(pv_value_t)); if(pv_get_spec_value(msg, spec, &val) < 0) { LM_DBG("Failed to get scriptvar value while executing cache_store\n"); ret=E_BUG; break; } if (!(val.flags&PV_VAL_INT)) { LM_ERR("Wrong value for cache_store expires, not an integer [%.*s]\n", val.rs.len, val.rs.s); } expires = val.ri; } else if ( a->elem[3].type == NUMBER_ST ) { expires = (int)a->elem[3].u.number; } ret = cachedb_store( &a->elem[0].u.s, &name_s, &val_s,expires); break; case CACHE_REMOVE_T: script_trace("core", "cache_remove", msg, a->line) ; if ((a->elem[0].type!=STR_ST)) { LM_ALERT("BUG in cache_remove() %d\n", a->elem[0].type ); ret=E_BUG; break; } if ((a->elem[1].type!=STR_ST)) { LM_ALERT("BUG in cache_remove() %d\n", a->elem[1].type ); ret=E_BUG; break; } /* parse the name argument */ pve = (pv_elem_t *)a->elem[1].u.data; if ( pv_printf_s(msg, pve, &name_s)!=0 || name_s.len == 0 || name_s.s == NULL) { LM_WARN("cannot get string for value\n"); ret=E_BUG; break; } ret = cachedb_remove( &a->elem[0].u.s, &name_s); break; case CACHE_FETCH_T: script_trace("core", "cache_fetch", msg, a->line) ; if ((a->elem[0].type!=STR_ST)) { LM_ALERT("BUG in cache_fetch() %d\n", a->elem[0].type ); ret=E_BUG; break; } if ((a->elem[1].type!=STR_ST)) { LM_ALERT("BUG in cache_fetch() %d\n", a->elem[1].type ); ret=E_BUG; break; } if (a->elem[2].type!=SCRIPTVAR_ST){ LM_ALERT("BUG in cache_fetch() type %d\n", a->elem[2].type); ret=E_BUG; break; } str aux = {0, 0}; /* parse the name argument */ pve = (pv_elem_t *)a->elem[1].u.data; if ( pv_printf_s(msg, pve, &name_s)!=0 || name_s.len == 0 || name_s.s == NULL) { LM_WARN("cannot get string for value\n"); ret=E_BUG; break; } ret = cachedb_fetch( &a->elem[0].u.s, &name_s, &aux); if(ret > 0) { val.rs = aux; val.flags = PV_VAL_STR; spec = (pv_spec_t*)a->elem[2].u.data; if (pv_set_value(msg, spec, 0, &val) < 0) { LM_ERR("cannot set the variable value\n"); pkg_free(aux.s); return -1; } pkg_free(aux.s); } break; case CACHE_COUNTER_FETCH_T: script_trace("core", "cache_counter_fetch", msg, a->line) ; if ((a->elem[0].type!=STR_ST)) { LM_ALERT("BUG in cache_fetch() %d\n", a->elem[0].type ); ret=E_BUG; break; } if ((a->elem[1].type!=STR_ST)) { LM_ALERT("BUG in cache_fetch() %d\n", a->elem[1].type ); ret=E_BUG; break; } if (a->elem[2].type!=SCRIPTVAR_ST){ LM_ALERT("BUG in cache_fetch() type %d\n", a->elem[2].type); ret=E_BUG; break; } int aux_counter; /* parse the name argument */ pve = (pv_elem_t *)a->elem[1].u.data; if ( pv_printf_s(msg, pve, &name_s)!=0 || name_s.len == 0 || name_s.s == NULL) { LM_WARN("cannot get string for value\n"); ret=E_BUG; break; } ret = cachedb_counter_fetch( &a->elem[0].u.s, &name_s, &aux_counter); if(ret > 0) { val.ri = aux_counter; val.flags = PV_TYPE_INT|PV_VAL_INT; spec = (pv_spec_t*)a->elem[2].u.data; if (pv_set_value(msg, spec, 0, &val) < 0) { LM_ERR("cannot set the variable value\n"); pkg_free(aux.s); return -1; } } break; case CACHE_ADD_T: script_trace("core", "cache_add", msg, a->line) ; if ((a->elem[0].type!=STR_ST)) { LM_ALERT("BUG in cache_add() - first argument not of" " type string [%d]\n", a->elem[0].type ); ret=E_BUG; break; } if ((a->elem[1].type!=STR_ST)) { LM_ALERT("BUG in cache_add() - second argument not of " "type string [%d]\n", a->elem[1].type ); ret=E_BUG; break; } /* parse the name argument */ pve = (pv_elem_t *)a->elem[1].u.data; if ( pv_printf_s(msg, pve, &name_s)!=0 || name_s.len == 0 || name_s.s == NULL) { LM_WARN("cannot get string for value\n"); ret=E_BUG; break; } int increment=0; /* get the increment value */ if ( a->elem[2].type == SCRIPTVAR_ST ) { spec = (pv_spec_t*)a->elem[2].u.data; memset(&val, 0, sizeof(pv_value_t)); if(pv_get_spec_value(msg, spec, &val) < 0) { LM_DBG("Failed to get scriptvar value while executing cache_add\n"); ret=E_BUG; break; } if (!(val.flags&PV_VAL_INT)) { LM_ERR("Wrong value for cache_add, not an integer [%.*s]\n", val.rs.len, val.rs.s); } increment = val.ri; } else if ( a->elem[2].type == NUMBER_ST ) { increment = (int)a->elem[2].u.number; } expires = (int)a->elem[3].u.number; /* TODO - return the new value to script ? */ ret = cachedb_add(&a->elem[0].u.s, &name_s, increment,expires,NULL); break; case CACHE_SUB_T: script_trace("core", "cache_sub", msg, a->line) ; if ((a->elem[0].type!=STR_ST)) { LM_ALERT("BUG in cache_sub() - first argument not of" " type string [%d]\n", a->elem[0].type ); ret=E_BUG; break; } if ((a->elem[1].type!=STR_ST)) { LM_ALERT("BUG in cache_sub() - second argument not of " "type string [%d]\n", a->elem[1].type ); ret=E_BUG; break; } /* parse the name argument */ pve = (pv_elem_t *)a->elem[1].u.data; if ( pv_printf_s(msg, pve, &name_s)!=0 || name_s.len == 0 || name_s.s == NULL) { LM_WARN("cannot get string for value\n"); ret=E_BUG; break; } int decrement=0; /* get the increment value */ if ( a->elem[2].type == SCRIPTVAR_ST ) { spec = (pv_spec_t*)a->elem[2].u.data; memset(&val, 0, sizeof(pv_value_t)); if(pv_get_spec_value(msg, spec, &val) < 0) { LM_DBG("Failed to get scriptvar value while executing cache_sub\n"); ret=E_BUG; break; } if (!(val.flags&PV_VAL_INT)) { LM_ERR("Wrong value for cache_sub, not an integer [%.*s]\n", val.rs.len, val.rs.s); } decrement = val.ri; } else if ( a->elem[2].type == NUMBER_ST ) { decrement = (int)a->elem[2].u.number; } expires = (int)a->elem[3].u.number; /* TODO - return new value to script ? */ ret = cachedb_sub(&a->elem[0].u.s, &name_s, decrement,expires,NULL); break; case CACHE_RAW_QUERY_T: if ((a->elem[0].type!=STR_ST)) { LM_ALERT("BUG in cache_fetch() %d\n", a->elem[0].type ); ret=E_BUG; break; } if ((a->elem[1].type!=STR_ST)) { LM_ALERT("BUG in cache_fetch() %d\n", a->elem[1].type ); ret=E_BUG; break; } if (a->elem[2].u.data != NULL && a->elem[2].type!=STR_ST){ LM_ALERT("BUG in cache_raw_query() type %d\n", a->elem[2].type); ret=E_BUG; break; } /* parse the name argument */ pve = (pv_elem_t *)a->elem[1].u.data; if ( pv_printf_s(msg, pve, &name_s)!=0 || name_s.len == 0 || name_s.s == NULL) { LM_WARN("cannot get string for value\n"); ret=E_BUG; break; } cdb_raw_entry **cdb_reply; int val_number=0,i,j; int key_number=0; pvname_list_t *cdb_res,*it; int_str avp_val; int_str avp_name; unsigned short avp_type; if (a->elem[2].u.data) { cdb_res = (pvname_list_t*)a->elem[2].u.data; for (it=cdb_res;it;it=it->next) val_number++; LM_DBG("The query expects %d results back\n",val_number); ret = cachedb_raw_query( &a->elem[0].u.s, &name_s, &cdb_reply,val_number,&key_number); if (ret >= 0 && val_number > 0) { for (i=key_number-1; i>=0;i--) { it=cdb_res; for (j=0;j < val_number;j++) { avp_type = 0; if (pv_get_avp_name(msg,&it->sname.pvp,&avp_name.n, &avp_type) != 0) { LM_ERR("cannot get avp name [%d/%d]\n",i,j); goto next_avp; } switch (cdb_reply[i][j].type) { case CDB_INT: avp_val.n = cdb_reply[i][j].val.n; break; case CDB_STR: avp_type |= AVP_VAL_STR; avp_val.s = cdb_reply[i][j].val.s; break; default: LM_WARN("Unknown type %d\n",cdb_reply[i][j].type); goto next_avp; } if (add_avp(avp_type,avp_name.n,avp_val) != 0) { LM_ERR("Unable to add AVP\n"); free_raw_fetch(cdb_reply,val_number,key_number); return -1; } next_avp: if (it) { it = it->next; if (it==NULL); break; } } } free_raw_fetch(cdb_reply,val_number,key_number); } } else ret = cachedb_raw_query( &a->elem[0].u.s, &name_s, NULL,0,NULL); break; case XDBG_T: script_trace("core", "xdbg", msg, a->line) ; if (a->elem[0].type == SCRIPTVAR_ELEM_ST) { if (xdbg(msg, a->elem[0].u.data, val.rs.s) < 0) { LM_ALERT("Cannot print message"); break; } } else { LM_ALERT("BUG in xdbg() type %d\n", a->elem[0].type); ret=E_BUG; } break; case XLOG_T: script_trace("core", "xlog", msg, a->line) ; if (a->elem[1].u.data != NULL) { if (a->elem[1].type != SCRIPTVAR_ELEM_ST) { LM_ALERT("BUG in xlog() type %d\n", a->elem[1].type); ret=E_BUG; break; } if (a->elem[0].type != STR_ST) { LM_ALERT("BUG in xlog() type %d\n", a->elem[0].type); ret=E_BUG; break; } if (xlog_2(msg,a->elem[0].u.data, a->elem[1].u.data) < 0) { LM_ALERT("Cannot print xlog debug message"); break; } } else { if (a->elem[0].type != SCRIPTVAR_ELEM_ST) { LM_ALERT("BUG in xlog() type %d\n", a->elem[0].type); ret=E_BUG; break; } if (xlog_1(msg,a->elem[0].u.data, val.rs.s) < 0) { LM_ALERT("Cannot print xlog debug message"); break; } } break; case RAISE_EVENT_T: script_trace("core", "raise_event", msg, a->line) ; if (a->elem[0].type != NUMBER_ST) { LM_ERR("invalid event id\n"); ret=E_BUG; break; } if (a->elem[2].u.data) { /* three parameters specified */ ret = evi_raise_script_event(msg, (event_id_t)a->elem[0].u.number, a->elem[1].u.data, a->elem[2].u.data); } else { /* two parameters specified */ ret = evi_raise_script_event(msg, (event_id_t)a->elem[0].u.number, NULL, a->elem[1].u.data); } if (ret <= 0) { LM_ERR("cannot raise event\n"); ret=E_UNSPEC; break; } break; case SUBSCRIBE_EVENT_T: script_trace("core", "subscribe_event", msg, a->line) ; if (a->elem[0].type != STR_ST || a->elem[1].type != STR_ST) { LM_ERR("BUG in subscribe arguments\n"); ret=E_BUG; break; } if (a->elem[2].u.data) { if (a->elem[2].type != NUMBER_ST) { LM_ERR("BUG in subscribe expiration time\n"); ret=E_BUG; break; } else { i = a->elem[2].u.number; } } else { i = 0; } name_s.s = a->elem[0].u.data; name_s.len = strlen(name_s.s); /* result should be the socket */ result.s = a->elem[1].u.data; result.len = strlen(result.s); ret = evi_event_subscribe(name_s, result, i, 0); break; case CONSTRUCT_URI_T: script_trace("core", "construct_uri", msg, a->line) ; for (i=0;i<5;i++) { pve = (pv_elem_t *)a->elem[i].u.data; if (pve->spec.getf) { if ( pv_printf_s(msg, pve, &vals[i])!=0 || vals[i].len == 0 || vals[i].s == NULL) { LM_WARN("cannot get string for value\n"); ret=E_BUG; return -1; } } else vals[i] = pve->text; } result.s = construct_uri(&vals[0],&vals[1],&vals[2],&vals[3],&vals[4], &result.len); if (result.s) { int_str res; int avp_name; unsigned short avp_type; spec = (pv_spec_t*)a->elem[5].u.data; if (pv_get_avp_name( msg, &(spec->pvp), &avp_name, &avp_type)!=0){ LM_CRIT("BUG in getting AVP name\n"); return -1; } res.s = result; if (add_avp(AVP_VAL_STR|avp_type, avp_name, res)<0){ LM_ERR("cannot add AVP\n"); return -1; } } break; case GET_TIMESTAMP_T: script_trace("core", "get_timestamp", msg, a->line) ; if (get_timestamp(&sec,&usec) == 0) { int avp_name; int_str res; unsigned short avp_type; spec = (pv_spec_t*)a->elem[0].u.data; if (pv_get_avp_name(msg, &(spec->pvp), &avp_name, &avp_type) != 0) { LM_CRIT("BUG in getting AVP name\n"); return -1; } res.n = sec; if (add_avp(avp_type, avp_name, res) < 0) { LM_ERR("cannot add AVP\n"); return -1; } spec = (pv_spec_t*)a->elem[1].u.data; if (pv_get_avp_name(msg, &(spec->pvp), &avp_name, &avp_type) != 0) { LM_CRIT("BUG in getting AVP name\n"); return -1; } res.n = usec; if (add_avp(avp_type, avp_name, res) < 0) { LM_ERR("cannot add AVP\n"); return -1; } } else { LM_ERR("failed to get time\n"); return -1; } break; case SWITCH_T: script_trace("core", "switch", msg, a->line) ; if (a->elem[0].type!=SCRIPTVAR_ST){ LM_ALERT("BUG in switch() type %d\n", a->elem[0].type); ret=E_BUG; break; } spec = (pv_spec_t*)a->elem[0].u.data; if(pv_get_spec_value(msg, spec, &val)!=0) { LM_ALERT("BUG - no value in switch()\n"); ret=E_BUG; break; } /* get the value of pvar */ if(a->elem[1].type!=ACTIONS_ST) { LM_ALERT("BUG in switch() actions\n"); ret=E_BUG; break; } return_code=1; adefault = NULL; aitem = (struct action*)a->elem[1].u.data; cmatch=0; while(aitem) { if((unsigned char)aitem->type==DEFAULT_T) adefault=aitem; if(cmatch==0) { if(aitem->elem[0].type==STR_ST) { if(val.flags&PV_VAL_STR && val.rs.len==aitem->elem[0].u.s.len && strncasecmp(val.rs.s, aitem->elem[0].u.s.s, val.rs.len)==0) cmatch = 1; } else { /* number */ if(val.flags&PV_VAL_INT && val.ri==aitem->elem[0].u.number) cmatch = 1; } } if(cmatch==1) { if(aitem->elem[1].u.data) { return_code=run_action_list( (struct action*)aitem->elem[1].u.data, msg); if ((action_flags&ACT_FL_RETURN) || (action_flags&ACT_FL_EXIT)) break; } if(aitem->elem[2].u.number==1) break; } aitem = aitem->next; } if((cmatch==0) && (adefault!=NULL)) { LM_DBG("switch: running default statement\n"); if(adefault->elem[0].u.data) return_code=run_action_list( (struct action*)adefault->elem[0].u.data, msg); } ret=return_code; break; case MODULE_T: script_trace("module", ((cmd_export_t*)(a->elem[0].u.data))->name, msg, a->line) ; if ( (a->elem[0].type==CMD_ST) && a->elem[0].u.data ) { ret=((cmd_export_t*)(a->elem[0].u.data))->function(msg, (char*)a->elem[1].u.data, (char*)a->elem[2].u.data, (char*)a->elem[3].u.data, (char*)a->elem[4].u.data, (char*)a->elem[5].u.data, (char*)a->elem[6].u.data); }else{ LM_ALERT("BUG in module call\n"); } break; case FORCE_RPORT_T: script_trace("core", "force_rport", msg, a->line) ; msg->msg_flags|=FL_FORCE_RPORT; ret=1; /* continue processing */ break; case FORCE_LOCAL_RPORT_T: script_trace("core", "force_local_rport", msg, a->line) ; msg->msg_flags|=FL_FORCE_LOCAL_RPORT; ret=1; /* continue processing */ break; case SET_ADV_ADDR_T: script_trace("core", "set_adv_addr", msg, a->line) ; if (a->elem[0].type!=STR_ST){ LM_ALERT("BUG in set_advertised_address() " "type %d\n", a->elem[0].type); ret=E_BUG; break; } str adv_addr; pve = (pv_elem_t *)a->elem[0].u.data; if ( pv_printf_s(msg, pve, &adv_addr)!=0 || adv_addr.len == 0 || adv_addr.s == NULL) { LM_WARN("cannot get string for value\n"); ret=E_BUG; break; } LM_DBG("adv address = [%.*s]\n",adv_addr.len,adv_addr.s); msg->set_global_address=adv_addr; ret=1; /* continue processing */ break; case SET_ADV_PORT_T: script_trace("core", "set_adv_port", msg, a->line) ; if (a->elem[0].type!=STR_ST){ LM_ALERT("BUG in set_advertised_port() " "type %d\n", a->elem[0].type); ret=E_BUG; break; } msg->set_global_port=*((str*)a->elem[0].u.data); ret=1; /* continue processing */ break; #ifdef USE_TCP case FORCE_TCP_ALIAS_T: script_trace("core", "force_tcp_alias", msg, a->line) ; if ( msg->rcv.proto==PROTO_TCP #ifdef USE_TLS || msg->rcv.proto==PROTO_TLS #endif ){ if (a->elem[0].type==NOSUBTYPE) port=msg->via1->port; else if (a->elem[0].type==NUMBER_ST) port=(int)a->elem[0].u.number; else{ LM_ALERT("BUG in force_tcp_alias" " port type %d\n", a->elem[0].type); ret=E_BUG; break; } if (tcpconn_add_alias(msg->rcv.proto_reserved1, port, msg->rcv.proto)!=0){ LM_ERR("tcp alias failed\n"); ret=E_UNSPEC; break; } } #endif ret=1; /* continue processing */ break; case FORCE_SEND_SOCKET_T: script_trace("core", "force_send_socket", msg, a->line) ; if (a->elem[0].type!=SOCKETINFO_ST){ LM_ALERT("BUG in force_send_socket argument" " type: %d\n", a->elem[0].type); ret=E_BUG; break; } msg->force_send_socket=(struct socket_info*)a->elem[0].u.data; ret=1; /* continue processing */ break; case SERIALIZE_BRANCHES_T: script_trace("core", "serialize_branches", msg, a->line) ; if (a->elem[0].type!=NUMBER_ST){ LM_ALERT("BUG in serialize_branches argument" " type: %d\n", a->elem[0].type); ret=E_BUG; break; } if (serialize_branches(msg,(int)a->elem[0].u.number)!=0) { LM_ERR("serialize_branches failed\n"); ret=E_UNSPEC; break; } ret=1; /* continue processing */ break; case NEXT_BRANCHES_T: script_trace("core", "next_branches", msg, a->line) ; if ((ret=next_branches(msg))<0) { LM_ERR("next_branches failed\n"); ret=E_UNSPEC; break; } /* continue processing */ break; case EQ_T: case COLONEQ_T: case PLUSEQ_T: case MINUSEQ_T: case DIVEQ_T: case MULTEQ_T: case MODULOEQ_T: case BANDEQ_T: case BOREQ_T: case BXOREQ_T: ret = do_assign(msg, a); break; case USE_BLACKLIST_T: script_trace("core", "use_blacklist", msg, a->line) ; mark_for_search((struct bl_head*)a->elem[0].u.data, 1); break; case UNUSE_BLACKLIST_T: script_trace("core", "unuse_blacklist", msg, a->line); mark_for_search((struct bl_head*)a->elem[0].u.data, 0); break; case PV_PRINTF_T: script_trace("core", "pv_printf", msg, a->line); ret = -1; spec = (pv_spec_p)a->elem[0].u.data; if(!pv_is_w(spec)) { LM_ERR("read only PV in first parameter of pv_printf\n"); goto error; } model = (pv_elem_p)a->elem[1].u.data; memset(&val, 0, sizeof(pv_value_t)); if(pv_printf_s(msg, model, &val.rs)!=0) { LM_ERR("cannot eval second parameter\n"); goto error; } val.flags = PV_VAL_STR; if(pv_set_value(msg, spec, EQ_T, &val)<0) { LM_ERR("setting PV failed\n"); goto error; } ret = 1; break; case SCRIPT_TRACE_T: script_trace("core", "script_trace", msg, a->line); if (a->elem[0].type==NOSUBTYPE) { use_script_trace = 0; } else { use_script_trace = 1; if (a->elem[0].type != NUMBER_ST || a->elem[1].type != SCRIPTVAR_ELEM_ST) { LM_ERR("BUG in use_script_trace() arguments\n"); ret=E_BUG; break; } if (a->elem[2].type!=NOSUBTYPE) { script_trace_info = (char *)a->elem[2].u.data; } else { script_trace_info = NULL; } script_trace_log_level = (int)a->elem[0].u.number; script_trace_elem = *(pv_elem_p)a->elem[1].u.data; } break; default: LM_ALERT("BUG - unknown type %d\n", a->type); goto error; } if((unsigned char)a->type!=IF_T && (unsigned char)a->type!=ROUTE_T) return_code = ret; /*skip:*/ update_longest_action(); return ret; error: LM_ERR("error at line: %d\n", a->line); update_longest_action(); return ret; error_uri: LM_ERR("set*: uri too long\n"); if (new_uri) pkg_free(new_uri); update_longest_action(); return E_UNSPEC; error_fwd_uri: update_longest_action(); return ret; }
/* execute assignment operation */ int do_assign(struct sip_msg* msg, struct action* a) { int ret; pv_value_t val; pv_spec_p dspec; ret = -1; dspec = (pv_spec_p)a->elem[0].u.data; if(!pv_is_w(dspec)) { LM_ERR("read only PV in left expression\n"); goto error; } memset(&val, 0, sizeof(pv_value_t)); if(a->elem[1].type != NULLV_ST) { ret = eval_expr((struct expr*)a->elem[1].u.data, msg, &val); if(!((val.flags&PV_VAL_STR)||(val.flags&PV_VAL_INT))) { LM_ERR("no value in right expression\n"); goto error; } } switch ((unsigned char)a->type){ case EQ_T: case COLONEQ_T: case PLUSEQ_T: case MINUSEQ_T: case DIVEQ_T: case MULTEQ_T: case MODULOEQ_T: case BANDEQ_T: case BOREQ_T: case BXOREQ_T: script_trace("assign", (unsigned char)a->type == EQ_T ? "equal" : (unsigned char)a->type == COLONEQ_T ? "colon-eq" : (unsigned char)a->type == PLUSEQ_T ? "plus-eq" : (unsigned char)a->type == MINUSEQ_T ? "minus-eq" : (unsigned char)a->type == DIVEQ_T ? "div-eq" : (unsigned char)a->type == MULTEQ_T ? "mult-eq" : (unsigned char)a->type == MODULOEQ_T? "modulo-eq" : (unsigned char)a->type == BANDEQ_T ? "b-and-eq" : (unsigned char)a->type == BOREQ_T ? "b-or-eq":"b-xor-eq", msg, a->line); if(a->elem[1].type == NULLV_ST) { if(pv_set_value(msg, dspec, (int)a->type, 0)<0) { LM_ERR("setting PV failed\n"); goto error; } } else { if(pv_set_value(msg, dspec, (int)a->type, &val)<0) { LM_ERR("setting PV failed\n"); goto error; } } ret = 1; break; default: LM_ALERT("BUG -> unknown op type %d\n", a->type); goto error; } pv_value_destroy(&val); return ret; error: LM_ERR("error at line: %d\n", a->line); pv_value_destroy(&val); return -1; }
/** * init module function */ static int mod_init(void) { m_tree_t *pt = NULL; if(mtree_init_rpc()!=0) { LM_ERR("failed to register RPC commands\n"); return -1; } if(pv_parse_spec(&value_param, &pv_value)<00 || !(pv_is_w(&pv_value))) { LM_ERR("cannot parse value pv or is read only\n"); return -1; } if (pv_parse_spec(&values_param, &pv_values) <0 || pv_values.type != PVT_AVP) { LM_ERR("cannot parse values avp\n"); return -1; } if(pv_parse_spec(&dstid_param, &pv_dstid)<0 || pv_dstid.type!=PVT_AVP) { LM_ERR("cannot parse dstid avp\n"); return -1; } if(pv_parse_spec(&weight_param, &pv_weight)<0 || pv_weight.type!=PVT_AVP) { LM_ERR("cannot parse dstid avp\n"); return -1; } if(pv_parse_spec(&count_param, &pv_count)<0 || !(pv_is_w(&pv_weight))) { LM_ERR("cannot parse count pv or is read-only\n"); return -1; } if(mt_fetch_rows<=0) mt_fetch_rows = 1000; if(mt_char_list.len<=0) { LM_ERR("invalid prefix char list\n"); return -1; } LM_DBG("mt_char_list=%s \n", mt_char_list.s); mt_char_table_init(); /* binding to mysql module */ if(db_bind_mod(&db_url, &mt_dbf)) { LM_ERR("database module not found\n"); return -1; } if (!DB_CAPABILITY(mt_dbf, DB_CAP_ALL)) { LM_ERR("database module does not " "implement all functions needed by the module\n"); return -1; } /* open a connection with the database */ db_con = mt_dbf.init(&db_url); if(db_con==NULL) { LM_ERR("failed to connect to the database\n"); return -1; } LM_DBG("database connection opened successfully\n"); if ( (mt_lock=lock_alloc())==0) { LM_CRIT("failed to alloc lock\n"); goto error1; } if (lock_init(mt_lock)==0 ) { LM_CRIT("failed to init lock\n"); goto error1; } if(mt_defined_trees()) { LM_DBG("static trees defined\n"); pt = mt_get_first_tree(); while(pt!=NULL) { LM_DBG("loading from tree <%.*s>\n", pt->tname.len, pt->tname.s); /* loading all information from database */ if(mt_load_db(pt)!=0) { LM_ERR("cannot load info from database\n"); goto error1; } pt = pt->next; } } else { if(db_table.len<=0) { LM_ERR("no trees table defined\n"); goto error1; } if(mt_init_list_head()<0) { LM_ERR("unable to init trees list head\n"); goto error1; } /* loading all information from database */ if(mt_load_db_trees()!=0) { LM_ERR("cannot load trees from database\n"); goto error1; } } mt_dbf.close(db_con); db_con = 0; #if 0 mt_print_tree(mt_get_first_tree()); #endif /* success code */ return 0; error1: if (mt_lock) { lock_destroy( mt_lock ); lock_dealloc( mt_lock ); mt_lock = 0; } mt_destroy_trees(); if(db_con!=NULL) mt_dbf.close(db_con); db_con = 0; return -1; }
/** * init module function */ static int mod_init(void) { LM_DBG("initializing ...\n"); if (check_if_default_head_is_ok()) { default_db_head.next = ds_db_heads; ds_db_heads = &default_db_head; } set_default_head_values(&default_db_head); ds_set_id_col.len = strlen(ds_set_id_col.s); ds_dest_uri_col.len = strlen(ds_dest_uri_col.s); ds_dest_sock_col.len = strlen(ds_dest_sock_col.s); ds_dest_state_col.len = strlen(ds_dest_state_col.s); ds_dest_weight_col.len = strlen(ds_dest_weight_col.s); ds_dest_attrs_col.len = strlen(ds_dest_attrs_col.s); if(hash_pvar_param.s && (hash_pvar_param.len=strlen(hash_pvar_param.s))>0){ if(pv_parse_format(&hash_pvar_param, &hash_param_model) < 0 || hash_param_model==NULL) { LM_ERR("malformed PV string: %s\n", hash_pvar_param.s); return -1; } } else { hash_param_model = NULL; } if(ds_setid_pvname.s && (ds_setid_pvname.len=strlen(ds_setid_pvname.s))>0){ if(pv_parse_spec(&ds_setid_pvname, &ds_setid_pv)==NULL || !pv_is_w(&ds_setid_pv)) { LM_ERR("[%s]- invalid setid_pvname\n", ds_setid_pvname.s); return -1; } } pvar_algo_param.len = strlen(pvar_algo_param.s); if (pvar_algo_param.len) ds_pvar_parse_pattern(pvar_algo_param); if (init_ds_bls()!=0) { LM_ERR("failed to init DS blacklists\n"); return E_CFG; } /* Creating partitions from head */ ds_db_head_t *head_it = ds_db_heads; while (head_it){ if (inherit_from_default_head(head_it) != 0) return -1; ds_partition_t *partition = shm_malloc (sizeof(ds_partition_t)); if (partition_init(head_it, partition) != 0) return -1; partition->next = partitions; partitions = partition; if (init_ds_data(partition)!=0) { LM_ERR("failed to init DS data holder\n"); return -1; } /* open DB connection to load provisioning data */ if (init_ds_db(partition)!= 0) { LM_ERR("failed to init database support\n"); return -1; } /* do the actual data load */ if (ds_reload_db(partition)!=0) { LM_ERR("failed to load data from DB\n"); return -1; } /* close DB connection */ ds_disconnect_db(partition); ds_db_head_t *aux = head_it; /* We keep track of corespondig default parition */ if (head_it == &default_db_head) default_partition = partition; head_it = head_it->next; if (aux != &default_db_head) pkg_free(aux); } /* Only, if the Probing-Timer is enabled the TM-API needs to be loaded: */ if (ds_ping_interval > 0) { load_tm_f load_tm; str host; int port,proto; if (ds_ping_from.s) ds_ping_from.len = strlen(ds_ping_from.s); if (ds_ping_method.s) ds_ping_method.len = strlen(ds_ping_method.s); /* parse the list of reply codes to be counted as success */ if(options_reply_codes_str.s) { options_reply_codes_str.len = strlen(options_reply_codes_str.s); if(parse_reply_codes(&options_reply_codes_str,&options_reply_codes, &options_codes_no )< 0) { LM_ERR("Bad format for options_reply_code parameter" " - Need a code list separated by commas\n"); return -1; } } /* parse and look for the socket to ping from */ if (probing_sock_s && probing_sock_s[0]!=0 ) { if (parse_phostport( probing_sock_s, strlen(probing_sock_s), &host.s, &host.len, &port, &proto)!=0 ) { LM_ERR("socket description <%s> is not valid\n", probing_sock_s); return -1; } probing_sock = grep_sock_info( &host, port, proto); if (probing_sock==NULL) { LM_ERR("socket <%s> is not local to opensips (we must listen " "on it\n", probing_sock_s); return -1; } } /* TM-Bindings */ load_tm=(load_tm_f)find_export("load_tm", 0, 0); if (load_tm==NULL) { LM_ERR("failed to bind to the TM-Module - required for probing\n"); return -1; } /* let the auto-loading function load all TM stuff */ if (load_tm( &tmb ) == -1) { LM_ERR("could not load the TM-functions - disable DS ping\n"); return -1; } /* Register the PING-Timer */ if (register_timer("ds-pinger", ds_check_timer, NULL, ds_ping_interval, TIMER_FLAG_DELAY_ON_DELAY)<0) { LM_ERR("failed to register timer for probing!\n"); return -1; } } /* register timer to flush the state of destination back to DB */ if (ds_persistent_state && register_timer("ds-flusher", ds_flusher_routine, NULL, 30 , TIMER_FLAG_SKIP_ON_DELAY)<0) { LM_ERR("failed to register timer for DB flushing!\n"); return -1; } dispatch_evi_id = evi_publish_event(dispatcher_event); if (dispatch_evi_id == EVI_ERROR) LM_ERR("cannot register dispatcher event\n"); return 0; }
/** * init module function */ static int mod_init(void) { pv_spec_t avp_spec; if(register_mi_mod(exports.name, mi_cmds)!=0) { LM_ERR("failed to register MI commands\n"); return -1; } if(ds_init_rpc()<0) { LM_ERR("failed to register RPC commands\n"); return -1; } if (dst_avp_param.s) dst_avp_param.len = strlen(dst_avp_param.s); if (grp_avp_param.s) grp_avp_param.len = strlen(grp_avp_param.s); if (cnt_avp_param.s) cnt_avp_param.len = strlen(cnt_avp_param.s); if (dstid_avp_param.s) dstid_avp_param.len = strlen(dstid_avp_param.s); if (attrs_avp_param.s) attrs_avp_param.len = strlen(attrs_avp_param.s); if (hash_pvar_param.s) hash_pvar_param.len = strlen(hash_pvar_param.s); if (ds_setid_pvname.s) ds_setid_pvname.len = strlen(ds_setid_pvname.s); if (ds_attrs_pvname.s) ds_attrs_pvname.len = strlen(ds_attrs_pvname.s); if (ds_ping_from.s) ds_ping_from.len = strlen(ds_ping_from.s); if (ds_ping_method.s) ds_ping_method.len = strlen(ds_ping_method.s); if (ds_outbound_proxy.s) ds_outbound_proxy.len = strlen(ds_outbound_proxy.s); if(cfg_declare("dispatcher", dispatcher_cfg_def, &default_dispatcher_cfg, cfg_sizeof(dispatcher), &dispatcher_cfg)){ LM_ERR("Fail to declare the configuration\n"); return -1; } /* Initialize the counter */ ds_ping_reply_codes = (int**)shm_malloc(sizeof(unsigned int*)); *ds_ping_reply_codes = 0; ds_ping_reply_codes_cnt = (int*)shm_malloc(sizeof(int)); *ds_ping_reply_codes_cnt = 0; if(ds_ping_reply_codes_str.s) { ds_ping_reply_codes_str.len = strlen(ds_ping_reply_codes_str.s); cfg_get(dispatcher, dispatcher_cfg, ds_ping_reply_codes_str) = ds_ping_reply_codes_str; if(ds_parse_reply_codes()< 0) { return -1; } } /* Copy Threshhold to Config */ cfg_get(dispatcher, dispatcher_cfg, probing_threshhold) = probing_threshhold; if(init_data()!= 0) return -1; if(ds_db_url.s) { ds_db_url.len = strlen(ds_db_url.s); ds_table_name.len = strlen(ds_table_name.s); ds_set_id_col.len = strlen(ds_set_id_col.s); ds_dest_uri_col.len = strlen(ds_dest_uri_col.s); ds_dest_flags_col.len = strlen(ds_dest_flags_col.s); ds_dest_priority_col.len = strlen(ds_dest_priority_col.s); ds_dest_attrs_col.len = strlen(ds_dest_attrs_col.s); if(init_ds_db()!= 0) { LM_ERR("could not initiate a connect to the database\n"); return -1; } } else { if(ds_load_list(dslistfile)!=0) { LM_ERR("no dispatching list loaded from file\n"); return -1; } else { LM_DBG("loaded dispatching list\n"); } } if (dst_avp_param.s && dst_avp_param.len > 0) { if (pv_parse_spec(&dst_avp_param, &avp_spec)==0 || avp_spec.type!=PVT_AVP) { LM_ERR("malformed or non AVP %.*s AVP definition\n", dst_avp_param.len, dst_avp_param.s); return -1; } if(pv_get_avp_name(0, &(avp_spec.pvp), &dst_avp_name, &dst_avp_type)!=0) { LM_ERR("[%.*s]- invalid AVP definition\n", dst_avp_param.len, dst_avp_param.s); return -1; } } else { dst_avp_name.n = 0; dst_avp_type = 0; } if (grp_avp_param.s && grp_avp_param.len > 0) { if (pv_parse_spec(&grp_avp_param, &avp_spec)==0 || avp_spec.type!=PVT_AVP) { LM_ERR("malformed or non AVP %.*s AVP definition\n", grp_avp_param.len, grp_avp_param.s); return -1; } if(pv_get_avp_name(0, &(avp_spec.pvp), &grp_avp_name, &grp_avp_type)!=0) { LM_ERR("[%.*s]- invalid AVP definition\n", grp_avp_param.len, grp_avp_param.s); return -1; } } else { grp_avp_name.n = 0; grp_avp_type = 0; } if (cnt_avp_param.s && cnt_avp_param.len > 0) { if (pv_parse_spec(&cnt_avp_param, &avp_spec)==0 || avp_spec.type!=PVT_AVP) { LM_ERR("malformed or non AVP %.*s AVP definition\n", cnt_avp_param.len, cnt_avp_param.s); return -1; } if(pv_get_avp_name(0, &(avp_spec.pvp), &cnt_avp_name, &cnt_avp_type)!=0) { LM_ERR("[%.*s]- invalid AVP definition\n", cnt_avp_param.len, cnt_avp_param.s); return -1; } } else { cnt_avp_name.n = 0; cnt_avp_type = 0; } if (dstid_avp_param.s && dstid_avp_param.len > 0) { if (pv_parse_spec(&dstid_avp_param, &avp_spec)==0 || avp_spec.type!=PVT_AVP) { LM_ERR("malformed or non AVP %.*s AVP definition\n", dstid_avp_param.len, dstid_avp_param.s); return -1; } if(pv_get_avp_name(0, &(avp_spec.pvp), &dstid_avp_name, &dstid_avp_type)!=0) { LM_ERR("[%.*s]- invalid AVP definition\n", dstid_avp_param.len, dstid_avp_param.s); return -1; } } else { dstid_avp_name.n = 0; dstid_avp_type = 0; } if (attrs_avp_param.s && attrs_avp_param.len > 0) { if (pv_parse_spec(&attrs_avp_param, &avp_spec)==0 || avp_spec.type!=PVT_AVP) { LM_ERR("malformed or non AVP %.*s AVP definition\n", attrs_avp_param.len, attrs_avp_param.s); return -1; } if(pv_get_avp_name(0, &(avp_spec.pvp), &attrs_avp_name, &attrs_avp_type)!=0) { LM_ERR("[%.*s]- invalid AVP definition\n", attrs_avp_param.len, attrs_avp_param.s); return -1; } } else { attrs_avp_name.n = 0; attrs_avp_type = 0; } if (hash_pvar_param.s && *hash_pvar_param.s) { if(pv_parse_format(&hash_pvar_param, &hash_param_model) < 0 || hash_param_model==NULL) { LM_ERR("malformed PV string: %s\n", hash_pvar_param.s); return -1; } } else { hash_param_model = NULL; } if(ds_setid_pvname.s!=0) { if(pv_parse_spec(&ds_setid_pvname, &ds_setid_pv)==NULL || !pv_is_w(&ds_setid_pv)) { LM_ERR("[%s]- invalid setid_pvname\n", ds_setid_pvname.s); return -1; } } if(ds_attrs_pvname.s!=0) { if(pv_parse_spec(&ds_attrs_pvname, &ds_attrs_pv)==NULL || !pv_is_w(&ds_attrs_pv)) { LM_ERR("[%s]- invalid attrs_pvname\n", ds_attrs_pvname.s); return -1; } } if (dstid_avp_param.s && dstid_avp_param.len > 0) { if(ds_hash_size>0) { if(ds_hash_load_init(1<<ds_hash_size, ds_hash_expire, ds_hash_initexpire)<0) return -1; register_timer(ds_ht_timer, NULL, ds_hash_check_interval); } else { LM_ERR("call load dispatching DSTID_AVP set but no size" " for hash table\n"); return -1; } } /* Only, if the Probing-Timer is enabled the TM-API needs to be loaded: */ if (ds_ping_interval > 0) { /***************************************************** * TM-Bindings *****************************************************/ if (load_tm_api( &tmb ) == -1) { LM_ERR("could not load the TM-functions - disable DS ping\n"); return -1; } /***************************************************** * Register the PING-Timer *****************************************************/ register_timer(ds_check_timer, NULL, ds_ping_interval); } return 0; }
/** * init module function */ static int mod_init(void) { pv_spec_t avp_spec; LM_DBG("initializing ...\n"); /* Load stuff from DB */ init_db_url( ds_db_url , 0 /*cannot be null*/); ds_table_name.len = strlen(ds_table_name.s); ds_set_id_col.len = strlen(ds_set_id_col.s); ds_dest_uri_col.len = strlen(ds_dest_uri_col.s); ds_dest_sock_col.len = strlen(ds_dest_sock_col.s); ds_dest_state_col.len = strlen(ds_dest_state_col.s); ds_dest_weight_col.len = strlen(ds_dest_weight_col.s); ds_dest_attrs_col.len = strlen(ds_dest_attrs_col.s); /* handle AVPs spec */ dst_avp_param.len = strlen(dst_avp_param.s); if (pv_parse_spec(&dst_avp_param, &avp_spec)==0 || avp_spec.type!=PVT_AVP) { LM_ERR("malformed or non AVP %.*s AVP definition\n", dst_avp_param.len, dst_avp_param.s); return -1; } if(pv_get_avp_name(0, &(avp_spec.pvp), &dst_avp_name,&dst_avp_type)!=0) { LM_ERR("[%.*s]- invalid AVP definition\n", dst_avp_param.len, dst_avp_param.s); return -1; } grp_avp_param.len=strlen(grp_avp_param.s); if (pv_parse_spec(&grp_avp_param, &avp_spec)==0 || avp_spec.type!=PVT_AVP) { LM_ERR("malformed or non AVP %.*s AVP definition\n", grp_avp_param.len, grp_avp_param.s); return -1; } if(pv_get_avp_name(0, &(avp_spec.pvp), &grp_avp_name,&grp_avp_type)!=0) { LM_ERR("[%.*s]- invalid AVP definition\n", grp_avp_param.len, grp_avp_param.s); return -1; } cnt_avp_param.len=strlen(cnt_avp_param.s); if (pv_parse_spec(&cnt_avp_param, &avp_spec)==0 || avp_spec.type!=PVT_AVP) { LM_ERR("malformed or non AVP %.*s AVP definition\n", cnt_avp_param.len, cnt_avp_param.s); return -1; } if(pv_get_avp_name(0, &(avp_spec.pvp), &cnt_avp_name,&cnt_avp_type)!=0) { LM_ERR("[%.*s]- invalid AVP definition\n", cnt_avp_param.len, cnt_avp_param.s); return -1; } sock_avp_param.len=strlen(sock_avp_param.s); if (pv_parse_spec(&sock_avp_param, &avp_spec)==0 || avp_spec.type!=PVT_AVP) { LM_ERR("malformed or non AVP %.*s AVP definition\n", sock_avp_param.len, sock_avp_param.s); return -1; } if(pv_get_avp_name(0, &(avp_spec.pvp), &sock_avp_name,&sock_avp_type)!=0){ LM_ERR("[%.*s]- invalid AVP definition\n", sock_avp_param.len, sock_avp_param.s); return -1; } if (attrs_avp_param.s && (attrs_avp_param.len=strlen(attrs_avp_param.s)) > 0) { if (pv_parse_spec(&attrs_avp_param, &avp_spec)==0 || avp_spec.type!=PVT_AVP) { LM_ERR("malformed or non AVP %.*s AVP definition\n", attrs_avp_param.len, attrs_avp_param.s); return -1; } if (pv_get_avp_name(0, &(avp_spec.pvp), &attrs_avp_name, &attrs_avp_type)!=0){ LM_ERR("[%.*s]- invalid AVP definition\n", attrs_avp_param.len, attrs_avp_param.s); return -1; } } else { attrs_avp_name = -1; attrs_avp_type = 0; } if (hash_pvar_param.s && (hash_pvar_param.len=strlen(hash_pvar_param.s))>0 ) { if(pv_parse_format(&hash_pvar_param, &hash_param_model) < 0 || hash_param_model==NULL) { LM_ERR("malformed PV string: %s\n", hash_pvar_param.s); return -1; } } else { hash_param_model = NULL; } if (ds_setid_pvname.s && (ds_setid_pvname.len=strlen(ds_setid_pvname.s))>0 ) { if(pv_parse_spec(&ds_setid_pvname, &ds_setid_pv)==NULL || !pv_is_w(&ds_setid_pv)) { LM_ERR("[%s]- invalid setid_pvname\n", ds_setid_pvname.s); return -1; } } pvar_algo_param.len = strlen(pvar_algo_param.s); if (pvar_algo_param.len) ds_pvar_parse_pattern(pvar_algo_param); if (init_ds_bls()!=0) { LM_ERR("failed to init DS blacklists\n"); return E_CFG; } if (init_ds_data()!=0) { LM_ERR("failed to init DS data holder\n"); return -1; } /* open DB connection to load provisioning data */ if (init_ds_db()!= 0) { LM_ERR("failed to init database support\n"); return -1; } /* do the actula data load */ if (ds_reload_db()!=0) { LM_ERR("failed to load data from DB\n"); return -1; } /* close DB connection */ ds_disconnect_db(); /* Only, if the Probing-Timer is enabled the TM-API needs to be loaded: */ if (ds_ping_interval > 0) { load_tm_f load_tm; str host; int port,proto; if (ds_ping_from.s) ds_ping_from.len = strlen(ds_ping_from.s); if (ds_ping_method.s) ds_ping_method.len = strlen(ds_ping_method.s); /* parse the list of reply codes to be counted as success */ if(options_reply_codes_str.s) { options_reply_codes_str.len = strlen(options_reply_codes_str.s); if(parse_reply_codes( &options_reply_codes_str, &options_reply_codes, &options_codes_no )< 0) { LM_ERR("Bad format for options_reply_code parameter" " - Need a code list separated by commas\n"); return -1; } } /* parse and look for the socket to ping from */ if (probing_sock_s && probing_sock_s[0]!=0 ) { if (parse_phostport( probing_sock_s, strlen(probing_sock_s), &host.s, &host.len, &port, &proto)!=0 ) { LM_ERR("socket description <%s> is not valid\n", probing_sock_s); return -1; } probing_sock = grep_sock_info( &host, port, proto); if (probing_sock==NULL) { LM_ERR("socket <%s> is not local to opensips (we must listen " "on it\n", probing_sock_s); return -1; } } /* TM-Bindings */ load_tm=(load_tm_f)find_export("load_tm", 0, 0); if (load_tm==NULL) { LM_ERR("failed to bind to the TM-Module - required for probing\n"); return -1; } /* let the auto-loading function load all TM stuff */ if (load_tm( &tmb ) == -1) { LM_ERR("could not load the TM-functions - disable DS ping\n"); return -1; } /* Register the PING-Timer */ if (register_timer("ds-pinger",ds_check_timer,NULL,ds_ping_interval)<0){ LM_ERR("failed to register timer for probing!\n"); return -1; } } /* register timer to flush the state of destination back to DB */ if (register_timer("ds-flusher",ds_flusher_routine,NULL, 30)<0){ LM_ERR("failed to register timer for DB flushing!\n"); return -1; } dispatch_evi_id = evi_publish_event(dispatcher_event); if (dispatch_evi_id == EVI_ERROR) LM_ERR("cannot register dispatcher event\n"); return 0; }
/** * init module function */ static int mod_init(void) { pv_spec_t avp_spec; LM_DBG("initializing ...\n"); if (dst_avp_param.s) dst_avp_param.len = strlen(dst_avp_param.s); if (grp_avp_param.s) grp_avp_param.len = strlen(grp_avp_param.s); if (cnt_avp_param.s) cnt_avp_param.len = strlen(cnt_avp_param.s); if (attrs_avp_param.s) attrs_avp_param.len = strlen(attrs_avp_param.s); if (hash_pvar_param.s) hash_pvar_param.len = strlen(hash_pvar_param.s); if (ds_setid_pvname.s) ds_setid_pvname.len = strlen(ds_setid_pvname.s); if (ds_ping_from.s) ds_ping_from.len = strlen(ds_ping_from.s); if (ds_ping_method.s) ds_ping_method.len = strlen(ds_ping_method.s); if(options_reply_codes_str.s) { options_reply_codes_str.len = strlen(options_reply_codes_str.s); if(parse_reply_codes( &options_reply_codes_str, &options_reply_codes, &options_codes_no )< 0) { LM_ERR("Bad format for options_reply_code parameter" " - Need a code list separated by commas\n"); return -1; } } if(init_data()!= 0) return -1; if(ds_db_url.s) { ds_db_url.len = strlen(ds_db_url.s); ds_table_name.len = strlen(ds_table_name.s); ds_set_id_col.len = strlen(ds_set_id_col.s); ds_dest_uri_col.len = strlen(ds_dest_uri_col.s); ds_dest_flags_col.len = strlen(ds_dest_flags_col.s); ds_dest_weight_col.len= strlen(ds_dest_weight_col.s); ds_dest_attrs_col.len = strlen(ds_dest_attrs_col.s); if(init_ds_db()!= 0) { LM_ERR("could not initiate a connect to the database\n"); return -1; } } else { if(ds_load_list(dslistfile)!=0) { LM_ERR("no dispatching list loaded from file\n"); return -1; } else { LM_DBG("loaded dispatching list\n"); } } if (dst_avp_param.s && dst_avp_param.len > 0) { if (pv_parse_spec(&dst_avp_param, &avp_spec)==0 || avp_spec.type!=PVT_AVP) { LM_ERR("malformed or non AVP %.*s AVP definition\n", dst_avp_param.len, dst_avp_param.s); return -1; } if(pv_get_avp_name(0, &(avp_spec.pvp), &dst_avp_name,&dst_avp_type)!=0) { LM_ERR("[%.*s]- invalid AVP definition\n", dst_avp_param.len, dst_avp_param.s); return -1; } } else { dst_avp_name.n = 0; dst_avp_type = 0; } if (grp_avp_param.s && grp_avp_param.len > 0) { if (pv_parse_spec(&grp_avp_param, &avp_spec)==0 || avp_spec.type!=PVT_AVP) { LM_ERR("malformed or non AVP %.*s AVP definition\n", grp_avp_param.len, grp_avp_param.s); return -1; } if(pv_get_avp_name(0, &(avp_spec.pvp), &grp_avp_name,&grp_avp_type)!=0) { LM_ERR("[%.*s]- invalid AVP definition\n", grp_avp_param.len, grp_avp_param.s); return -1; } } else { grp_avp_name.n = 0; grp_avp_type = 0; } if (cnt_avp_param.s && cnt_avp_param.len > 0) { if (pv_parse_spec(&cnt_avp_param, &avp_spec)==0 || avp_spec.type!=PVT_AVP) { LM_ERR("malformed or non AVP %.*s AVP definition\n", cnt_avp_param.len, cnt_avp_param.s); return -1; } if(pv_get_avp_name(0, &(avp_spec.pvp), &cnt_avp_name,&cnt_avp_type)!=0) { LM_ERR("[%.*s]- invalid AVP definition\n", cnt_avp_param.len, cnt_avp_param.s); return -1; } } else { cnt_avp_name.n = 0; cnt_avp_type = 0; } if (attrs_avp_param.s && attrs_avp_param.len > 0) { if (pv_parse_spec(&attrs_avp_param, &avp_spec)==0 || avp_spec.type!=PVT_AVP) { LM_ERR("malformed or non AVP %.*s AVP definition\n", attrs_avp_param.len, attrs_avp_param.s); return -1; } if (pv_get_avp_name(0, &(avp_spec.pvp), &attrs_avp_name, &attrs_avp_type)!=0){ LM_ERR("[%.*s]- invalid AVP definition\n", attrs_avp_param.len, attrs_avp_param.s); return -1; } } else { attrs_avp_name.n = 0; attrs_avp_type = 0; } if (hash_pvar_param.s && *hash_pvar_param.s) { if(pv_parse_format(&hash_pvar_param, &hash_param_model) < 0 || hash_param_model==NULL) { LM_ERR("malformed PV string: %s\n", hash_pvar_param.s); return -1; } } else { hash_param_model = NULL; } if(ds_setid_pvname.s!=0) { if(pv_parse_spec(&ds_setid_pvname, &ds_setid_pv)==NULL || !pv_is_w(&ds_setid_pv)) { LM_ERR("[%s]- invalid setid_pvname\n", ds_setid_pvname.s); return -1; } } /* Only, if the Probing-Timer is enabled the TM-API needs to be loaded: */ if (ds_ping_interval > 0) { load_tm_f load_tm; str host; int port,proto; if (probing_sock_s && probing_sock_s[0]!=0 ) { if (parse_phostport( probing_sock_s, strlen(probing_sock_s), &host.s, &host.len, &port, &proto)!=0 ) { LM_ERR("socket description <%s> is not valid\n", probing_sock_s); return -1; } probing_sock = grep_sock_info( &host, port, proto); if (probing_sock==NULL) { LM_ERR("socket <%s> is not local to opensips (we must listen " "on it\n", probing_sock_s); return -1; } } /* TM-Bindings */ load_tm=(load_tm_f)find_export("load_tm", 0, 0); if (load_tm==NULL) { LM_ERR("failed to bind to the TM-Module - required for probing\n"); return -1; } /* let the auto-loading function load all TM stuff */ if (load_tm( &tmb ) == -1) { LM_ERR("could not load the TM-functions - disable DS ping\n"); return -1; } /* Register the PING-Timer */ if (register_timer(ds_check_timer, NULL, ds_ping_interval)<0) { LM_ERR("failed to register timer for probing!\n"); return -1; } } return 0; }
/** * init module function */ static int mod_init(void) { pv_spec_t avp_spec; str host; int port, proto; if(register_mi_mod(exports.name, mi_cmds)!=0) { LM_ERR("failed to register MI commands\n"); return -1; } if(ds_ping_active_init()<0) { return -1; } if(ds_init_rpc()<0) { LM_ERR("failed to register RPC commands\n"); return -1; } if(cfg_declare("dispatcher", dispatcher_cfg_def, &default_dispatcher_cfg, cfg_sizeof(dispatcher), &dispatcher_cfg)){ LM_ERR("Fail to declare the configuration\n"); return -1; } /* Initialize the counter */ ds_ping_reply_codes = (int**)shm_malloc(sizeof(unsigned int*)); *ds_ping_reply_codes = 0; ds_ping_reply_codes_cnt = (int*)shm_malloc(sizeof(int)); *ds_ping_reply_codes_cnt = 0; if(ds_ping_reply_codes_str.s) { cfg_get(dispatcher, dispatcher_cfg, ds_ping_reply_codes_str) = ds_ping_reply_codes_str; if(ds_parse_reply_codes()< 0) { return -1; } } /* copy threshholds to config */ cfg_get(dispatcher, dispatcher_cfg, probing_threshold) = probing_threshold; cfg_get(dispatcher, dispatcher_cfg, inactive_threshold) = inactive_threshold; if (ds_default_socket.s && ds_default_socket.len > 0) { if (parse_phostport( ds_default_socket.s, &host.s, &host.len, &port, &proto)!=0) { LM_ERR("bad socket <%.*s>\n", ds_default_socket.len, ds_default_socket.s); return -1; } ds_default_sockinfo = grep_sock_info( &host, (unsigned short)port, proto); if (ds_default_sockinfo==0) { LM_WARN("non-local socket <%.*s>\n", ds_default_socket.len, ds_default_socket.s); return -1; } LM_INFO("default dispatcher socket set to <%.*s>\n", ds_default_socket.len, ds_default_socket.s); } if(init_data()!= 0) return -1; if(ds_db_url.s) { if(init_ds_db()!= 0) { LM_ERR("could not initiate a connect to the database\n"); return -1; } } else { if(ds_load_list(dslistfile)!=0) { LM_ERR("no dispatching list loaded from file\n"); return -1; } else { LM_DBG("loaded dispatching list\n"); } } if (dst_avp_param.s && dst_avp_param.len > 0) { if (pv_parse_spec(&dst_avp_param, &avp_spec)==0 || avp_spec.type!=PVT_AVP) { LM_ERR("malformed or non AVP %.*s AVP definition\n", dst_avp_param.len, dst_avp_param.s); return -1; } if(pv_get_avp_name(0, &(avp_spec.pvp), &dst_avp_name, &dst_avp_type)!=0) { LM_ERR("[%.*s]- invalid AVP definition\n", dst_avp_param.len, dst_avp_param.s); return -1; } } else { dst_avp_name.n = 0; dst_avp_type = 0; } if (grp_avp_param.s && grp_avp_param.len > 0) { if (pv_parse_spec(&grp_avp_param, &avp_spec)==0 || avp_spec.type!=PVT_AVP) { LM_ERR("malformed or non AVP %.*s AVP definition\n", grp_avp_param.len, grp_avp_param.s); return -1; } if(pv_get_avp_name(0, &(avp_spec.pvp), &grp_avp_name, &grp_avp_type)!=0) { LM_ERR("[%.*s]- invalid AVP definition\n", grp_avp_param.len, grp_avp_param.s); return -1; } } else { grp_avp_name.n = 0; grp_avp_type = 0; } if (cnt_avp_param.s && cnt_avp_param.len > 0) { if (pv_parse_spec(&cnt_avp_param, &avp_spec)==0 || avp_spec.type!=PVT_AVP) { LM_ERR("malformed or non AVP %.*s AVP definition\n", cnt_avp_param.len, cnt_avp_param.s); return -1; } if(pv_get_avp_name(0, &(avp_spec.pvp), &cnt_avp_name, &cnt_avp_type)!=0) { LM_ERR("[%.*s]- invalid AVP definition\n", cnt_avp_param.len, cnt_avp_param.s); return -1; } } else { cnt_avp_name.n = 0; cnt_avp_type = 0; } if (dstid_avp_param.s && dstid_avp_param.len > 0) { if (pv_parse_spec(&dstid_avp_param, &avp_spec)==0 || avp_spec.type!=PVT_AVP) { LM_ERR("malformed or non AVP %.*s AVP definition\n", dstid_avp_param.len, dstid_avp_param.s); return -1; } if(pv_get_avp_name(0, &(avp_spec.pvp), &dstid_avp_name, &dstid_avp_type)!=0) { LM_ERR("[%.*s]- invalid AVP definition\n", dstid_avp_param.len, dstid_avp_param.s); return -1; } } else { dstid_avp_name.n = 0; dstid_avp_type = 0; } if (attrs_avp_param.s && attrs_avp_param.len > 0) { if (pv_parse_spec(&attrs_avp_param, &avp_spec)==0 || avp_spec.type!=PVT_AVP) { LM_ERR("malformed or non AVP %.*s AVP definition\n", attrs_avp_param.len, attrs_avp_param.s); return -1; } if(pv_get_avp_name(0, &(avp_spec.pvp), &attrs_avp_name, &attrs_avp_type)!=0) { LM_ERR("[%.*s]- invalid AVP definition\n", attrs_avp_param.len, attrs_avp_param.s); return -1; } } else { attrs_avp_name.n = 0; attrs_avp_type = 0; } if (sock_avp_param.s && sock_avp_param.len > 0) { if (pv_parse_spec(&sock_avp_param, &avp_spec)==0 || avp_spec.type!=PVT_AVP) { LM_ERR("malformed or non AVP %.*s AVP definition\n", sock_avp_param.len, sock_avp_param.s); return -1; } if(pv_get_avp_name(0, &(avp_spec.pvp), &sock_avp_name, &sock_avp_type)!=0) { LM_ERR("[%.*s]- invalid AVP definition\n", sock_avp_param.len, sock_avp_param.s); return -1; } } else { sock_avp_name.n = 0; sock_avp_type = 0; } if (hash_pvar_param.s && *hash_pvar_param.s) { if(pv_parse_format(&hash_pvar_param, &hash_param_model) < 0 || hash_param_model==NULL) { LM_ERR("malformed PV string: %s\n", hash_pvar_param.s); return -1; } } else { hash_param_model = NULL; } if(ds_setid_pvname.s!=0) { if(pv_parse_spec(&ds_setid_pvname, &ds_setid_pv)==NULL || !pv_is_w(&ds_setid_pv)) { LM_ERR("[%s]- invalid setid_pvname\n", ds_setid_pvname.s); return -1; } } if(ds_attrs_pvname.s!=0) { if(pv_parse_spec(&ds_attrs_pvname, &ds_attrs_pv)==NULL || !pv_is_w(&ds_attrs_pv)) { LM_ERR("[%s]- invalid attrs_pvname\n", ds_attrs_pvname.s); return -1; } } if (dstid_avp_param.s && dstid_avp_param.len > 0) { if(ds_hash_size>0) { if(ds_hash_load_init(1<<ds_hash_size, ds_hash_expire, ds_hash_initexpire)<0) return -1; if(ds_timer_mode==1) { if(sr_wtimer_add(ds_ht_timer, NULL, ds_hash_check_interval)<0) return -1; } else { if(register_timer(ds_ht_timer, NULL, ds_hash_check_interval)<0) return -1; } } else { LM_ERR("call load dispatching DSTID_AVP set but no size" " for hash table (see ds_hash_size parameter)\n"); return -1; } } /* Only, if the Probing-Timer is enabled the TM-API needs to be loaded: */ if (ds_ping_interval > 0) { /***************************************************** * TM-Bindings *****************************************************/ if (load_tm_api( &tmb ) == -1) { LM_ERR("could not load the TM-functions - disable DS ping\n"); return -1; } /***************************************************** * Register the PING-Timer *****************************************************/ if(ds_timer_mode==1) { if(sr_wtimer_add(ds_check_timer, NULL, ds_ping_interval)<0) return -1; } else { if(register_timer(ds_check_timer, NULL, ds_ping_interval)<0) return -1; } } return 0; }