static void set_output_pv_params(struct sip_msg *msg, str *body_in, pv_spec_p body_pv, str *ctype_in, pv_spec_p ctype_pv, CURL *handle, pv_spec_p code_pv) { pv_value_t val; long http_rc; CURLcode rc; val.flags = PV_VAL_STR; val.rs = *body_in; if (pv_set_value(msg, (pv_spec_p)body_pv, 0, &val) != 0) LM_ERR("failed to set output body pv\n"); if (ctype_pv) { val.rs = *ctype_in; if (pv_set_value(msg, (pv_spec_p)ctype_pv, 0, &val) != 0) LM_ERR("failed to set output ctype pv\n"); } if (code_pv) { rc = curl_easy_getinfo(handle, CURLINFO_RESPONSE_CODE, &http_rc); if (rc != CURLE_OK) LM_ERR("curl_easy_getinfo: %s\n", curl_easy_strerror(rc)); LM_DBG("Last response code: %ld\n", http_rc); val.flags = PV_VAL_INT|PV_TYPE_INT; val.ri = (int)http_rc; if (pv_set_value(msg, (pv_spec_p)code_pv, 0, &val) != 0) LM_ERR("failed to set output code pv\n"); } }
static int dp_update(struct sip_msg * msg, pv_spec_t * src, pv_spec_t * dest, str * repl, str * attrs) { pv_value_t val; if (repl->s && repl->len) { val.flags = PV_VAL_STR; val.rs = *repl; if (pv_set_value( msg, dest, 0, &val)!=0) { LM_ERR("falied to set the output value!\n"); return -1; } } if(!attr_pvar) return 0; val.flags = PV_VAL_STR; val.rs = *attrs; if (pv_set_value( msg, attr_pvar, 0, &val)!=0) { LM_ERR("falied to set the attr value!\n"); return -1; } return 0; }
static int read_and_write2var(struct sip_msg* msg, FILE** strm, gparam_p outvar) { #define MAX_LINE_SIZE 1024 #define MAX_BUF_SIZE 32 * MAX_LINE_SIZE int buflen=0, tmplen; pv_value_t outval; char buf[MAX_BUF_SIZE], tmpbuf[MAX_LINE_SIZE]; while((tmplen=fread(tmpbuf, 1, MAX_LINE_SIZE, *strm))) { if ((buflen + tmplen) >= MAX_BUF_SIZE) { LM_WARN("no more space in output buffer\n"); break; } memcpy(buf+buflen, tmpbuf, tmplen); buflen += tmplen; } outval.flags = PV_VAL_STR; outval.rs.s = buf; outval.rs.len = buflen; if (buflen && pv_set_value(msg, &outvar->v.pve->spec, 0, &outval) < 0) { LM_ERR("cannot set output pv value\n"); return -1; } return 0; #undef MAX_LINE_SIZE #undef MAX_BUF_SIZE }
/** * Function that runs a JSON-RPC request * Returns: * -1: internal error * -2: communication error * -3: reply error * 1: success */ static int jrpc_request(struct sip_msg *msg, union sockaddr_union *dst, str *method, str *params, pv_spec_p spec) { int id, ret; char *cmd; pv_value_t val; id = jsonrpc_unique_id(); cmd = jsonrpc_build_cmd(method, params, &id); if (!cmd) { LM_ERR("cannot build jsonrpc command \n"); return -1; } ret = jsonrpc_handle_cmd(dst, cmd, &id, &val); cJSON_PurgeString(cmd); if (ret == -2) { LM_ERR("communication error with %s:%hu\n", JSONRPC_PRINT(dst)); return ret; } if (pv_set_value(msg, spec, 0, &val) < 0) { LM_ERR("cannot set returned value!\n"); ret = -1; } /* XXX: free the value returned */ if ((val.flags & PV_VAL_STR) && !(val.flags & PV_VAL_INT)) cJSON_PurgeString(val.rs.s); return ret; }
static int pv_set_count(struct sip_msg* msg, pv_spec_t *pv_name, pv_spec_t *pv_result) { pv_value_t pv_val; memset(&pv_val, 0, sizeof(pv_value_t)); pv_name->pvp.pvi.type = PV_IDX_INT; pv_name->pvp.pvi.u.ival = 0; while(pv_val.flags != PV_VAL_NULL) { if(pv_get_spec_value(msg, pv_name, &pv_val) < 0) { LM_ERR("PV get function failed\n"); return -1; } pv_name->pvp.pvi.u.ival++; } pv_val.flags = PV_TYPE_INT; pv_val.ri = pv_name->pvp.pvi.u.ival-1; if (pv_set_value( msg, pv_result, 0, &pv_val) != 0) { LM_ERR("SET output value failed.\n"); return -1; } LM_DBG("Set count = %d\n", pv_val.ri); return 1; }
int cmd_send_req(struct sip_msg *msg, int *cluster_id, int *node_id, str *gen_msg, pv_spec_t *param_tag) { pv_value_t tag_val; int rc; /* generate tag */ generate_msg_tag(&tag_val, *cluster_id); if (param_tag && pv_set_value(msg, param_tag, 0, &tag_val) < 0) { LM_ERR("Unable to set tag pvar\n"); return -1; } rc = send_gen_msg(*cluster_id, *node_id, gen_msg, &tag_val.rs, 1); switch (rc) { case 0: return 1; case 1: return -1; case -1: return -2; case -2: return -3; default: return -3; } }
static int ts_usec_delta(struct sip_msg *msg, int *t1s, int *t1u, int *t2s, int *t2u, pv_spec_t *_res) { pv_value_t res; res.ri = abs(1000000 * (*t1s - *t2s) + *t1u - *t2u); res.flags = PV_TYPE_INT; if (pv_set_value(msg, _res, 0, &res)) { LM_ERR("cannot store result value\n"); return -1; } return 1; }
static int scriptroute_add_param(struct sip_msg *msg, struct scriptroute_params *param) { int index; evi_param_t *it = parameters->first; pv_value_t val; if (param->index) { /* search the parameter by it's index */ for (index = 1; it && index != param->index; it = it->next, index++); if (!it) { LM_WARN("Parameter %d not found - max %d\n", param->index, index); return 0; } } else { /* specified by name */ for (; it; it = it->next) { if (it->name.s && it->name.len == param->name.len && memcmp(it->name.s, param->name.s, it->name.len) == 0) break; } if (!it) { LM_WARN("Parameter <%.*s> not found for event <%.*s>\n", param->name.len, param->name.s, event_name->len, event_name->s); return 0; } } /* parameter found - populate it */ if (it->flags & EVI_INT_VAL) { val.ri = it->val.n; val.flags = PV_VAL_INT|PV_TYPE_INT; } else { val.rs.len = it->val.s.len; val.rs.s = it->val.s.s; val.flags = PV_VAL_STR; } if (pv_set_value(msg, ¶m->spec, 0, &val) < 0) { LM_WARN("cannot populate parameter\n"); return 0; } return 1; }
int cmd_send_req(struct sip_msg *msg, char *param_cluster, char *param_node, char *param_msg, char *param_tag) { int cluster_id, node_id; str gen_msg; pv_value_t tag_val; int rc; if (fixup_get_ivalue(msg, (gparam_p)param_cluster, &cluster_id) < 0) { LM_ERR("Failed to fetch cluster id parameter\n"); return -1; } if (fixup_get_ivalue(msg, (gparam_p)param_node, &node_id) < 0) { LM_ERR("Failed to fetch node id parameter\n"); return -1; } if (fixup_get_svalue(msg, (gparam_p)param_msg, &gen_msg) < 0) { LM_ERR("Failed to fetch message parameter\n"); return -1; } /* generate tag */ generate_msg_tag(&tag_val, cluster_id); if (param_tag && pv_set_value(msg, (pv_spec_p)param_tag, 0, &tag_val) < 0) { LM_ERR("Unable to set tag pvar\n"); return -1; } rc = send_gen_msg(cluster_id, node_id, &gen_msg, &tag_val.rs, 1); switch (rc) { case 0: return 1; case 1: return -1; case -1: return -2; case -2: return -3; default: return -3; } }
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; }
inline int set_alias_to_pvar(struct sip_msg* _msg, str *alias, int no, void *p) { pv_value_t val; pv_spec_t *pvs=(pv_spec_t*)p; if(no && !ald_append_branches) return 0; /* set the PVAR */ val.flags = PV_VAL_STR; val.ri = 0; val.rs = *alias; if(pv_set_value(_msg, pvs, (int)(no?EQ_T:COLONEQ_T), &val)<0) { LM_ERR("setting PV AVP failed\n"); return -1; } return 0; }
/** * Set the dialog's AVP value so the dialog module will use this value * and not the default when returning from the dialog callback. * * @param msg The current message to bind the AVP to. * @param value The value you want to set the AVP to. * * @return 0 on success, -1 on an error. */ static int set_timeout_avp(struct sip_msg *msg, unsigned int value) { int rtn = -1; /* assume failure */ pv_value_t pv_val; int result = 0; /* Set the dialog timeout HERE */ if (timeout_avp) { if ((result = pv_get_spec_value(msg, timeout_avp, &pv_val)) == 0) { /* We now hold a reference to the AVP */ if (pv_val.flags & PV_VAL_INT && pv_val.ri == value) { /* INT AVP with the same value */ LM_DBG("Current timeout value already set to %d\n", value); rtn = 0; } else { /* AVP not found or non-INT value -> add a new one*/ pv_val.flags = PV_VAL_INT|PV_TYPE_INT; pv_val.ri = value; if (pv_set_value(msg,timeout_avp,EQ_T,&pv_val)!=0) { LM_ERR("failed to set new dialog timeout value\n"); } else { LM_DBG("set dialog timeout value to %d\n", value); rtn = 0; } } } else { LM_ERR("SST not reset. get avp result is %d\n", result); } } else { LM_ERR("SST needs to know the name of the dialog timeout AVP!\n"); } return(rtn); }
int get_source_group(struct sip_msg* msg, char *arg) { int group = -1; struct in_addr in; struct ip_addr *ip; str str_ip, partition; pv_value_t pvt; struct part_pvar *ppv; struct pm_part_struct *ps; ppv = (struct part_pvar *)arg; if (ppv->part) { if (fixup_get_svalue(msg, ppv->part, &partition)) { LM_ERR("cannot get partition value\n"); return -1; } str_trim_spaces_lr(partition); ps = get_part_struct(&partition); if (ps == NULL) { LM_ERR("no such partition (%.*s)\n", partition.len, partition.s); return -1; } } else { ps = get_part_struct(&def_part); if (ps == NULL) { LM_ERR("no default partition\n"); return -1; } } LM_DBG("Looking for <%x, %u> in address table\n", msg->rcv.src_ip.u.addr32[0], msg->rcv.src_port); in.s_addr = msg->rcv.src_ip.u.addr32[0]; str_ip.s = inet_ntoa(in); str_ip.len = str_ip.s ? strlen(str_ip.s) : 0; ip = str2ip(&str_ip); group = find_group_in_hash_table(*ps->hash_table, ip, msg->rcv.src_port); group=0; LM_DBG("Found <%d>\n", group); if (group == -1) { LM_DBG("Looking for <%x, %u> in subnet table\n", msg->rcv.src_ip.u.addr32[0], msg->rcv.src_port); /* TODO FIX INPUT PARAMS*/ group = find_group_in_subnet_table(*ps->subnet_table, ip, msg->rcv.src_port); group = 0; LM_DBG("Found <%d>\n", group); } pvt.flags = PV_VAL_INT|PV_TYPE_INT; pvt.rs.s = NULL; pvt.rs.len = 0; pvt.ri = group; if (pv_set_value(msg, ppv->sp, (int)EQ_T, &pvt) < 0) { LM_ERR("setting of pvar failed\n"); return -1; } return 1; }
/** * rest_post_method - performs an HTTP POST request, stores results in pvars * @msg: sip message struct * @url: HTTP URL to be queried * @ctype: Value for the "Content-Type: " header of the request * @body: Body of the request * @body_pv: pseudo var which will hold the result body * @ctype_pv: pvar which will hold the result content type * @code_pv: pvar to hold the HTTP return code */ int rest_post_method(struct sip_msg *msg, char *url, char *body, char *ctype, pv_spec_p body_pv, pv_spec_p ctype_pv, pv_spec_p code_pv) { CURLcode rc; CURL *handle = NULL; long http_rc; str st = { 0, 0 }; str res_body = { 0, 0 }; pv_value_t pv_val; handle = curl_easy_init(); if (!handle) { LM_ERR("Init curl handle failed!\n"); clean_header_list; return -1; } if (ctype) { sprintf(print_buff, "Content-Type: %s", ctype); header_list = curl_slist_append(header_list, print_buff); } if (header_list) w_curl_easy_setopt(handle, CURLOPT_HTTPHEADER, header_list); w_curl_easy_setopt(handle, CURLOPT_URL, url); w_curl_easy_setopt(handle, CURLOPT_POST, 1); w_curl_easy_setopt(handle, CURLOPT_POSTFIELDS, body); w_curl_easy_setopt(handle, CURLOPT_CONNECTTIMEOUT, connection_timeout); w_curl_easy_setopt(handle, CURLOPT_TIMEOUT, curl_timeout); w_curl_easy_setopt(handle, CURLOPT_VERBOSE, 1); w_curl_easy_setopt(handle, CURLOPT_STDERR, stdout); w_curl_easy_setopt(handle, CURLOPT_FAILONERROR, 1); w_curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, write_func); w_curl_easy_setopt(handle, CURLOPT_WRITEDATA, &res_body); w_curl_easy_setopt(handle, CURLOPT_HEADERFUNCTION, header_func); w_curl_easy_setopt(handle, CURLOPT_HEADERDATA, &st); if (ssl_capath) w_curl_easy_setopt(handle, CURLOPT_CAPATH, ssl_capath); if (!ssl_verifypeer) w_curl_easy_setopt(handle, CURLOPT_SSL_VERIFYPEER, 0L); if (!ssl_verifyhost) w_curl_easy_setopt(handle, CURLOPT_SSL_VERIFYHOST, 0L); rc = curl_easy_perform(handle); clean_header_list; if (code_pv) { curl_easy_getinfo(handle, CURLINFO_RESPONSE_CODE, &http_rc); LM_DBG("Last response code: %ld\n", http_rc); pv_val.flags = PV_VAL_INT|PV_TYPE_INT; pv_val.ri = (int)http_rc; if (pv_set_value(msg, code_pv, 0, &pv_val) != 0) { LM_ERR("Set code pv value failed!\n"); goto cleanup; } } if (rc != CURLE_OK) { LM_ERR("curl_easy_perform: %s\n", curl_easy_strerror(rc)); goto cleanup; } trim(&res_body); pv_val.flags = PV_VAL_STR; pv_val.rs = res_body; if (pv_set_value(msg, body_pv, 0, &pv_val) != 0) { LM_ERR("Set body pv value failed!\n"); goto cleanup; } if (res_body.s) { pkg_free(res_body.s); } if (ctype_pv) { pv_val.rs = st; if (pv_set_value(msg, ctype_pv, 0, &pv_val) != 0) { LM_ERR("Set content type pv value failed!\n"); goto cleanup; } if (st.s) pkg_free(st.s); } curl_easy_cleanup(handle); return 1; cleanup: curl_easy_cleanup(handle); return -1; }
enum async_ret_code resume_async_http_req(int fd, struct sip_msg *msg, void *_param) { CURLcode rc; CURLMcode mrc; rest_async_param *param = (rest_async_param *)_param; int running, max_fd; long http_rc; fd_set rset, wset, eset; pv_value_t val; mrc = curl_multi_perform(multi_handle, &running); if (mrc != CURLM_OK) { LM_ERR("curl_multi_perform: %s\n", curl_multi_strerror(mrc)); return -1; } LM_DBG("running handles: %d\n", running); if (running == running_handles) { async_status = ASYNC_CONTINUE; return 1; } if (running > running_handles) { LM_BUG("incremented handles!!"); /* default async status is DONE */ return -1; } running_handles = running; FD_ZERO(&rset); mrc = curl_multi_fdset(multi_handle, &rset, &wset, &eset, &max_fd); if (mrc != CURLM_OK) { LM_ERR("curl_multi_fdset: %s\n", curl_multi_strerror(mrc)); /* default async status is DONE */ return -1; } if (max_fd == -1) { if (running_handles != 0) { LM_BUG("running_handles == %d", running_handles); abort(); /* default async status is DONE */ return -1; } if (FD_ISSET(fd, &rset)) { LM_BUG("fd %d is still in rset!", fd); abort(); /* default async status is DONE */ return -1; } } else if (FD_ISSET(fd, &rset)) { LM_DBG("fd %d still transfering...\n", fd); async_status = ASYNC_CONTINUE; return 1; } if (del_transfer(fd) != 0) { LM_BUG("failed to delete fd %d", fd); abort(); /* default async status is DONE */ return -1; } mrc = curl_multi_remove_handle(multi_handle, param->handle); if (mrc != CURLM_OK) { LM_ERR("curl_multi_remove_handle: %s\n", curl_multi_strerror(mrc)); /* default async status is DONE */ return -1; } val.flags = PV_VAL_STR; val.rs = param->body; if (pv_set_value(msg, param->body_pv, 0, &val) != 0) LM_ERR("failed to set output body pv\n"); if (param->ctype_pv) { val.rs = param->ctype; if (pv_set_value(msg, param->ctype_pv, 0, &val) != 0) LM_ERR("failed to set output ctype pv\n"); } if (param->code_pv) { rc = curl_easy_getinfo(param->handle, CURLINFO_RESPONSE_CODE, &http_rc); if (rc != CURLE_OK) { LM_ERR("curl_easy_getinfo: %s\n", curl_easy_strerror(rc)); http_rc = 0; } LM_DBG("Last response code: %ld\n", http_rc); val.flags = PV_VAL_INT|PV_TYPE_INT; val.ri = (int)http_rc; if (pv_set_value(msg, param->code_pv, 0, &val) != 0) LM_ERR("failed to set output code pv\n"); } pkg_free(param->body.s); if (param->ctype_pv && param->ctype.s) pkg_free(param->ctype.s); curl_easy_cleanup(param->handle); pkg_free(param); /* default async status is DONE */ return 1; }
/** * rest_put_method - performs an HTTP PUT request, stores results in pvars * @msg: sip message struct * @url: HTTP URL to be queried * @ctype: Value for the "Content-Type: " header of the request * @body: Body of the request * @body_pv: pseudo var which will hold the result body * @ctype_pv: pvar which will hold the result content type * @code_pv: pvar to hold the HTTP return code */ int rest_put_method(struct sip_msg *msg, char *url, char *body, char *ctype, pv_spec_p body_pv, pv_spec_p ctype_pv, pv_spec_p code_pv) { CURLcode rc; long http_rc; str st = { 0, 0 }; str res_body = { NULL, 0 }, tbody, ttype; pv_value_t pv_val; rest_trace_param_t tparam; /*Init handle for first use*/ if (!sync_handle) { sync_handle = curl_easy_init(); if (!sync_handle) { LM_ERR("Init curl handle failed!\n"); goto cleanup; } } else { curl_easy_reset(sync_handle); } if (ctype) { sprintf(print_buff, "Content-Type: %s", ctype); header_list = curl_slist_append(header_list, print_buff); } if (tls_dom) { w_curl_easy_setopt(sync_handle, CURLOPT_SSLCERT, tls_dom->cert.s); w_curl_easy_setopt(sync_handle, CURLOPT_SSLKEY, tls_dom->pkey.s); tls_api.release_domain(tls_dom); tls_dom = NULL; } if (header_list) w_curl_easy_setopt(sync_handle, CURLOPT_HTTPHEADER, header_list); w_curl_easy_setopt(sync_handle, CURLOPT_URL, url); if (curl_http_version != CURL_HTTP_VERSION_NONE) w_curl_easy_setopt(sync_handle, CURLOPT_HTTP_VERSION, curl_http_version); w_curl_easy_setopt(sync_handle, CURLOPT_CUSTOMREQUEST, "PUT"); w_curl_easy_setopt(sync_handle, CURLOPT_POSTFIELDS, body); w_curl_easy_setopt(sync_handle, CURLOPT_CONNECTTIMEOUT, connection_timeout); w_curl_easy_setopt(sync_handle, CURLOPT_TIMEOUT, curl_timeout); w_curl_easy_setopt(sync_handle, CURLOPT_VERBOSE, 1); w_curl_easy_setopt(sync_handle, CURLOPT_STDERR, stdout); w_curl_easy_setopt(sync_handle, CURLOPT_FAILONERROR, 0); w_curl_easy_setopt(sync_handle, CURLOPT_WRITEFUNCTION, write_func); w_curl_easy_setopt(sync_handle, CURLOPT_WRITEDATA, &res_body); w_curl_easy_setopt(sync_handle, CURLOPT_HEADERFUNCTION, header_func); w_curl_easy_setopt(sync_handle, CURLOPT_HEADERDATA, &st); if (ssl_capath) w_curl_easy_setopt(sync_handle, CURLOPT_CAPATH, ssl_capath); if (!ssl_verifypeer) w_curl_easy_setopt(sync_handle, CURLOPT_SSL_VERIFYPEER, 0L); if (!ssl_verifyhost) w_curl_easy_setopt(sync_handle, CURLOPT_SSL_VERIFYHOST, 0L); /* trace rest request */ if ( rest_trace_enabled() ) { memset( &tparam, 0, sizeof tparam); tparam.callid = msg->callid->body; w_curl_easy_setopt(sync_handle, CURLOPT_DEBUGFUNCTION, trace_rest_request_cb); w_curl_easy_setopt(sync_handle, CURLOPT_DEBUGDATA, &tparam); } rc = curl_easy_perform(sync_handle); clean_header_list; if (code_pv) { curl_easy_getinfo(sync_handle, CURLINFO_RESPONSE_CODE, &http_rc); LM_DBG("Last response code: %ld\n", http_rc); pv_val.flags = PV_VAL_INT|PV_TYPE_INT; pv_val.ri = (int)http_rc; if (pv_set_value(msg, code_pv, 0, &pv_val) != 0) { LM_ERR("Set code pv value failed!\n"); return -1; } } if (rc != CURLE_OK) { LM_ERR("curl_easy_perform: %s\n", curl_easy_strerror(rc)); return -1; } tbody = res_body; trim(&tbody); pv_val.flags = PV_VAL_STR; pv_val.rs = tbody; if (pv_set_value(msg, body_pv, 0, &pv_val) != 0) { LM_ERR("Set body pv value failed!\n"); return -1; } if (res_body.s) { pkg_free(res_body.s); } if (ctype_pv) { ttype = st; trim(&ttype); pv_val.rs = ttype; if (pv_set_value(msg, ctype_pv, 0, &pv_val) != 0) { LM_ERR("Set content type pv value failed!\n"); return -1; } } if (st.s) pkg_free(st.s); return 1; cleanup: clean_header_list; if (tls_dom) { tls_api.release_domain(tls_dom); tls_dom = NULL; } return -1; }
enum async_ret_code resume_async_http_req(int fd, struct sip_msg *msg, void *_param) { CURLcode rc; CURLMcode mrc; rest_async_param *param = (rest_async_param *)_param; int running = 0, max_fd; long http_rc; fd_set rset, wset, eset; pv_value_t val; int ret = 1, retr; CURLM *multi_handle; multi_handle = param->multi_list->multi_handle; retr = 0; do { mrc = curl_multi_perform(multi_handle, &running); if (mrc != CURLM_CALL_MULTI_PERFORM) break; LM_DBG("retry last perform...\n"); usleep(_async_resume_retr_itv); retr += _async_resume_retr_itv; } while (retr < _async_resume_retr_timeout); if (mrc != CURLM_OK) { LM_ERR("curl_multi_perform: %s\n", curl_multi_strerror(mrc)); return -1; } LM_DBG("running handles: %d\n", running); if (running == 1) { LM_DBG("transfer in progress...\n"); async_status = ASYNC_CONTINUE; return 1; } if (running != 0) { LM_BUG("non-zero running handles!! (%d)", running); abort(); } FD_ZERO(&rset); mrc = curl_multi_fdset(multi_handle, &rset, &wset, &eset, &max_fd); if (mrc != CURLM_OK) { LM_ERR("curl_multi_fdset: %s\n", curl_multi_strerror(mrc)); ret = -1; goto out; } if (max_fd == -1) { if (FD_ISSET(fd, &rset)) { LM_BUG("fd %d is still in rset!", fd); abort(); } } else if (FD_ISSET(fd, &rset)) { LM_DBG("fd %d still transferring...\n", fd); async_status = ASYNC_CONTINUE; return 1; } curl_slist_free_all(param->header_list); if (del_transfer(fd) != 0) { LM_BUG("failed to delete fd %d", fd); abort(); } mrc = curl_multi_remove_handle(multi_handle, param->handle); if (mrc != CURLM_OK) { LM_ERR("curl_multi_remove_handle: %s\n", curl_multi_strerror(mrc)); /* default async status is ASYNC_DONE */ return -1; } put_multi(param->multi_list); val.flags = PV_VAL_STR; val.rs = param->body; if (pv_set_value(msg, param->body_pv, 0, &val) != 0) LM_ERR("failed to set output body pv\n"); if (param->ctype_pv) { val.rs = param->ctype; if (pv_set_value(msg, param->ctype_pv, 0, &val) != 0) LM_ERR("failed to set output ctype pv\n"); } if (param->code_pv) { rc = curl_easy_getinfo(param->handle, CURLINFO_RESPONSE_CODE, &http_rc); if (rc != CURLE_OK) { LM_ERR("curl_easy_getinfo: %s\n", curl_easy_strerror(rc)); http_rc = 0; } LM_DBG("Last response code: %ld\n", http_rc); val.flags = PV_VAL_INT|PV_TYPE_INT; val.ri = (int)http_rc; if (pv_set_value(msg, param->code_pv, 0, &val) != 0) LM_ERR("failed to set output code pv\n"); } out: pkg_free(param->body.s); if (param->ctype_pv && param->ctype.s) pkg_free(param->ctype.s); curl_easy_cleanup(param->handle); if ( param->tparam ) { pkg_free( param->tparam ); } pkg_free(param); /* default async status is ASYNC_DONE */ return ret; }
static int dp_translate_f(struct sip_msg *msg, char *str1, char *str2, char *attr_spec) { int dpid; str input, output; dpl_id_p idp; dp_param_p id_par, repl_par; str attrs, *attrs_par; dp_connection_list_p connection; pv_value_t pval; str partition_name; if (!msg) return -1; /* verify first param's value */ id_par = (dp_param_p) str1; if (dp_get_ivalue(msg, id_par, &dpid) != 0){ LM_ERR("no dpid value\n"); return -1; } switch( id_par->type ) { case DP_VAL_INT : if (dp_get_svalue(msg, id_par->v.pv_id.partition, &partition_name)) { LM_ERR("invalid partition\n"); return -1; } goto GET_CONN; case DP_VAL_SPEC : if (dp_get_svalue(msg, id_par->v.sp[1], &partition_name)) { LM_ERR("invalid partition\n"); return -1; } GET_CONN: if (!(id_par->hash = dp_get_connection(&partition_name))) { LM_ERR("invalid partition\n"); return -1; } break; default : break; } LM_DBG("dpid is %i partition is %.*s\n", dpid, id_par->hash->partition.len, id_par->hash->partition.s); repl_par = (str2!=NULL) ? ((dp_param_p)str2) : default_par2; if (dp_get_svalue(msg, repl_par->v.sp[0], &input)!=0){ LM_ERR("invalid param 2\n"); return -1; } LM_DBG("input is %.*s\n", input.len, input.s); connection = id_par->hash; /* ref the data for reading */ lock_start_read( connection->ref_lock ); if ((idp = select_dpid(connection, dpid, connection->crt_index)) == 0) { LM_DBG("no information available for dpid %i\n", dpid); goto error; } LM_DBG("Checking with dpid %i\n", idp->dp_id); attrs_par = attr_spec ? &attrs : NULL; if (translate(msg, input, &output, idp, attrs_par) != 0) { LM_DBG("could not translate %.*s " "with dpid %i\n", input.len, input.s, idp->dp_id); goto error; } LM_DBG("input %.*s with dpid %i => output %.*s\n", input.len, input.s, idp->dp_id, output.len, output.s); /* set the output */ if (dp_update(msg, &repl_par->v.sp[0], &repl_par->v.sp[1], &output) != 0) { LM_ERR("cannot set the output\n"); goto error; } /* we are done reading -> unref the data */ lock_stop_read( connection->ref_lock ); if (attr_spec) { pval.flags = PV_VAL_STR; pval.rs = attrs; if (pv_set_value(msg, (pv_spec_p)attr_spec, 0, &pval) != 0) { LM_ERR("failed to set value '%.*s' for the attr pvar!\n", attrs.len, attrs.s); goto error; } } return 1; error: /* we are done reading -> unref the data */ lock_stop_read( connection->ref_lock ); return -1; }
/* Checks, if the request (sip_msg *_m) comes from a host in a set * (set-id or -1 for all sets) */ int ds_is_in_list(struct sip_msg *_m, pv_spec_t *pv_ip, pv_spec_t *pv_port, int set, int active_only) { pv_value_t val; ds_set_p list; struct ip_addr *ip; int_str avp_val; int port; int j,k; /* get the address to test */ if (pv_get_spec_value( _m, pv_ip, &val)!=0) { LM_ERR("failed to get IP value from PV\n"); return -1; } if ( (val.flags&PV_VAL_STR)==0 ) { LM_ERR("IP PV val is not string\n"); return -1; } if ( (ip=str2ip( &val.rs ))==NULL ) { LM_ERR("IP val is not IP <%.*s>\n",val.rs.len,val.rs.s); return -1; } /* get the port to test */ if (pv_port) { if (pv_get_spec_value( _m, pv_port, &val)!=0) { LM_ERR("failed to get PORT value from PV\n"); return -1; } if ( (val.flags&PV_VAL_INT)==0 ) { LM_ERR("PORT PV val is not integer\n"); return -1; } port = val.ri; } else { port = 0; } memset(&val, 0, sizeof(pv_value_t)); val.flags = PV_VAL_INT|PV_TYPE_INT; for(list = _ds_list; list!= NULL; list= list->next) { if ((set == -1) || (set == list->id)) { /* interate through all elements/destinations in the list */ for(j=0; j<list->nr; j++) { /* interate through all IPs of each destination */ for(k=0 ; k<list->dlist[j].ips_cnt ; k++ ) { if ( (list->dlist[j].ports[k]==0 || port==0 || port==list->dlist[j].ports[k]) && ip_addr_cmp( ip, &list->dlist[j].ips[k]) ) { /* matching destination */ if (active_only && (list->dlist[j].flags&(DS_INACTIVE_DST|DS_PROBING_DST)) ) continue; if(set==-1 && ds_setid_pvname.s!=0) { val.ri = list->id; if(pv_set_value(_m, &ds_setid_pv, (int)EQ_T, &val)<0) { LM_ERR("setting PV failed\n"); return -2; } } if (attrs_avp_name>= 0) { avp_val.s = list->dlist[j].attrs; if(add_avp(AVP_VAL_STR|attrs_avp_type,attrs_avp_name,avp_val)!=0) return -1; } return 1; } } } } } 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; }
/* * Check if domain is local */ int is_domain_local(struct sip_msg *msg, str* _host, char *pvar) { pv_spec_t *pv = (pv_spec_t *)pvar; pv_value_t val; db_val_t *values; if (db_mode == 0) { db_key_t keys[1]; db_val_t vals[1]; db_key_t cols[2]; db_res_t* res = NULL; keys[0] = &domain_col; cols[0] = &domain_col; cols[1] = &domain_attrs_col; if (domain_dbf.use_table(db_handle, &domain_table) < 0) { LM_ERR("Error while trying to use domain table\n"); return -3; } VAL_TYPE(vals) = DB_STR; VAL_NULL(vals) = 0; VAL_STR(vals).s = _host->s; VAL_STR(vals).len = _host->len; if (domain_dbf.query(db_handle, keys, 0, vals, cols, 1, 2, 0, &res) < 0 ) { LM_ERR("Error while querying database\n"); return -3; } if (RES_ROW_N(res) == 0) { LM_DBG("Realm '%.*s' is not local\n", _host->len, ZSW(_host->s)); domain_dbf.free_result(db_handle, res); return -1; } else { LM_DBG("Realm '%.*s' is local\n", _host->len, ZSW(_host->s)); if (pvar) { /* XXX: what shall we do if there are duplicate entries? */ /* we only check the first row - razvanc */ values = ROW_VALUES(RES_ROWS(res)); if (!VAL_NULL(values +1)) { if (VAL_TYPE(values + 1) == DB_STR) { val.rs = VAL_STR(values + 1); } else { val.rs.s = (char *)VAL_STRING(values + 1); val.rs.len = strlen(val.rs.s); } val.flags = PV_VAL_STR; if (pv_set_value(msg, pv, 0, &val) != 0) LM_ERR("Cannot set attributes value\n"); } } domain_dbf.free_result(db_handle, res); return 1; } } else { return hash_table_lookup (msg, _host, pv); } }
int ds_count(struct sip_msg *msg, int set_id, const char *cmp, pv_spec_p ret) { pv_value_t pv_val; ds_set_p set; ds_dest_p dst; int count, active = 0, inactive = 0, probing = 0; set = ds_lists[*crt_idx]; LM_DBG("Searching for set: %d, filtering: %d\n", set_id, *cmp); while (set && set->id != set_id) { set = set->next; } if (!set) { LM_ERR("INVALID SET!\n"); return -1; } for (dst = set->dlist; dst; dst = dst->next) { if (!(dst->flags & (DS_INACTIVE_DST|DS_PROBING_DST))) { active++; } else if (dst->flags & DS_INACTIVE_DST) { inactive++; } else if (dst->flags & DS_PROBING_DST) { probing++; } } switch (*cmp) { case DS_COUNT_ACTIVE: count = active; break; case DS_COUNT_ACTIVE|DS_COUNT_INACTIVE: case DS_COUNT_ACTIVE|DS_COUNT_PROBING: count = (*cmp & DS_COUNT_INACTIVE ? active + inactive : active + probing); break; case DS_COUNT_INACTIVE: case DS_COUNT_PROBING: count = (*cmp == DS_COUNT_INACTIVE ? inactive : probing); break; case DS_COUNT_INACTIVE|DS_COUNT_PROBING: count = inactive + probing; break; default: count = active + inactive + probing; } pv_val.flags = PV_TYPE_INT; pv_val.ri = count; if (pv_set_value(msg, ret, 0, &pv_val) != 0) { LM_ERR("SET OUTPUT value failed!\n"); return -1; } return 1; }
int async_rest_method(enum rest_client_method method, struct sip_msg *msg, char *url, str *body, str *ctype, async_ctx *ctx, pv_spec_p body_pv, pv_spec_p ctype_pv, pv_spec_p code_pv) { rest_async_param *param; pv_value_t val; long http_rc; int read_fd, rc; param = pkg_malloc(sizeof *param); if (!param) { LM_ERR("no more shm\n"); return RCL_INTERNAL_ERR; } memset(param, '\0', sizeof *param); rc = start_async_http_req(msg, method, url, body, ctype, param, ¶m->body, ctype_pv ? ¶m->ctype : NULL, &read_fd); /* error occurred; no transfer done */ if (read_fd == ASYNC_NO_IO) { ctx->resume_param = NULL; ctx->resume_f = NULL; /* keep default async status of NO_IO */ pkg_free(param); return rc; /* no need for async - transfer already completed! */ } else if (read_fd == ASYNC_SYNC) { if (code_pv) { curl_easy_getinfo(param->handle, CURLINFO_RESPONSE_CODE, &http_rc); LM_DBG("HTTP response code: %ld\n", http_rc); val.flags = PV_VAL_INT|PV_TYPE_INT; val.ri = (int)http_rc; if (pv_set_value(msg, (pv_spec_p)code_pv, 0, &val) != 0) { LM_ERR("failed to set output code pv\n"); return RCL_INTERNAL_ERR; } } val.flags = PV_VAL_STR; val.rs = param->body; if (pv_set_value(msg, (pv_spec_p)body_pv, 0, &val) != 0) { LM_ERR("failed to set output body pv\n"); return RCL_INTERNAL_ERR; } if (ctype_pv) { val.rs = param->ctype; if (pv_set_value(msg, (pv_spec_p)ctype_pv, 0, &val) != 0) { LM_ERR("failed to set output ctype pv\n"); return RCL_INTERNAL_ERR; } } pkg_free(param->body.s); if (ctype_pv && param->ctype.s) pkg_free(param->ctype.s); curl_easy_cleanup(param->handle); pkg_free(param); async_status = ASYNC_SYNC; return rc; } ctx->resume_f = resume_async_http_req; param->method = method; param->body_pv = (pv_spec_p)body_pv; param->ctype_pv = (pv_spec_p)ctype_pv; param->code_pv = (pv_spec_p)code_pv; ctx->resume_param = param; /* async started with success */ async_status = read_fd; return 1; }
int get_user_group(struct sip_msg *req, char *user, char *avp) { static char uri_buf[MAX_URI_SIZE]; str user_str; str username; str domain; pv_spec_t *pvs; pv_value_t val; struct re_grp *rg; regmatch_t pmatch; char *c; int n; if(user == NULL || fixup_get_svalue(req, (gparam_p)user, &user_str) != 0){ LM_ERR("Invalid parameter URI\n"); return -1; } if (get_username_domain( req, &user_str, &username, &domain)!=0){ LM_ERR("failed to get username@domain\n"); goto error; } if (username.s==NULL || username.len==0 ) { LM_DBG("no username part\n"); return -1; } if ( 4 + username.len + 1 + domain.len + 1 > MAX_URI_SIZE ) { LM_ERR("URI to large!!\n"); goto error; } *(int*)uri_buf = htonl(('s'<<24) + ('i'<<16) + ('p'<<8) + ':'); c = uri_buf + 4; memcpy( c, username.s, username.len); c += username.len; *(c++) = '@'; memcpy( c, domain.s, domain.len); c += domain.len; *c = 0; LM_DBG("getting groups for <%s>\n",uri_buf); pvs = (pv_spec_t*)avp; memset(&val, 0, sizeof(pv_value_t)); val.flags = PV_VAL_INT|PV_TYPE_INT; /* check against all re groups */ for( rg=re_list,n=0 ; rg ; rg=rg->next ) { if (regexec( &rg->re, uri_buf, 1, &pmatch, 0)==0) { LM_DBG("user matched to group %d!\n", rg->gid.n); /* match -> add the gid as AVP */ val.ri = rg->gid.n; if(pv_set_value(req, pvs, (int)EQ_T, &val)<0) { LM_ERR("setting PV AVP failed\n"); goto error; } n++; /* continue? */ if (multiple_gid==0) break; } } return n?n:-1; error: return -1; }
/* 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; }
int resume_async_exec(int fd, struct sip_msg *msg, void *param) { #define MAX_LINE_SIZE 1024 char buf[MAX_LINE_SIZE+1]; exec_async_param *p = (exec_async_param*)param; pv_value_t outval; char *s1, *s2; int n, len; if (p->buf) { memcpy( buf, p->buf, p->buf_len); len = p->buf_len; shm_free(p->buf); p->buf = NULL; } else { len = 0; } do { n=read( fd, buf+len, MAX_LINE_SIZE-len); LM_DBG(" read %d [%.*s] \n",n, n<0?0:n,buf+len); if (n<0) { if (errno==EINTR) continue; if (errno==EAGAIN || errno==EWOULDBLOCK) { /* nothing more to read */ if (len) { /* store what is left */ if ((p->buf=(char*)shm_malloc(len))==NULL) { LM_ERR("failed to allocate buffer\n"); goto error; } memcpy( p->buf, buf, len); p->buf_len = len; LM_DBG(" storing %d [%.*s] \n", p->buf_len, p->buf_len, p->buf); } /* async should continue */ async_status = ASYNC_CONTINUE; return 1; } LM_ERR("read failed with %d (%s)\n",errno, strerror(errno)); /* terminate everything */ goto error; } /* EOF ? */ if (n==0) { if (len) { /* take whatever is left in buffer and push it as var */ outval.flags = PV_VAL_STR; outval.rs.s = buf; outval.rs.len = len; LM_DBG("setting var [%.*s]\n",outval.rs.len,outval.rs.s); if (pv_set_value(msg, &p->outvar->v.pve->spec, 0, &outval) < 0) { LM_ERR("failed to set variable :(, continuing \n"); } } break; } /* successful reading ( n>0 ) */ LM_DBG(" having %d [%.*s] \n", len+n, len+n, buf); if (n+len==MAX_LINE_SIZE) { /* we have full buffer, pack it as a line */ buf[n+len] = '\n'; n++; } /* search for '\n' in the newly read data */ s1 = buf; while ( (buf+len+n-s1>0) && ((s2=q_memchr(s1, '\n', buf+len+n-s1))!=NULL) ) { /* push it as var */ outval.flags = PV_VAL_STR; outval.rs.s = s1; outval.rs.len = s2-s1; LM_DBG("setting var [%.*s]\n",outval.rs.len,outval.rs.s); if (pv_set_value(msg, &p->outvar->v.pve->spec, 0, &outval) < 0) { LM_ERR("failed to set variable :(, continuing \n"); } s1 = s2+1; } /* any data consumed ? */ if ( s1!=buf+len ) { /* yes -> shift the whole buffer to left */ len = buf+len+n-s1; if (len) memmove( buf, s1, len); } else { /* no -> increase the len of the buffer */ len += n; } }while(1); /* done with the async */ shm_free(param); /* make sure our fd is closed by the async engine */ async_status = ASYNC_DONE_CLOSE_FD; return 1; error: shm_free(param); /* stay with default async status ASYNC_DONE */ return -1; #undef MAX_LINE_SIZE }
int send_auth_func(struct sip_msg* msg, str* s1, str* s2) { int i, res; int index1 = -1, index2 = -1; map_list *mp; pv_value_t pvt; char mess[1024]; VALUE_PAIR *send = NULL, *recv = NULL, *vp = NULL; if (!rh) { if (init_radius_handle()) { LM_ERR("invalid radius handle\n"); return -1; } } for (i = 0; i < set_size; i++) { if (sets[i]->set_name.len == s1->len && !strncmp(sets[i]->set_name.s, s1->s, s1->len)) index1 = i; if (sets[i]->set_name.len == s2->len && !strncmp(sets[i]->set_name.s, s2->s, s2->len)) index2 = i; } if (index1 == -1) { LM_ERR("the first set was not found\n"); return -1; } if (index2 == -1) { LM_ERR("the second set was not found\n"); return -1; } if (make_send_message(msg, index1, &send) < 0) { LM_ERR("make message failed\n"); return -1; } res = rc_auth(rh, SIP_PORT, send, &recv, mess); if (res!=OK_RC && res!=BADRESP_RC) { LM_ERR("radius authentication message failed with %s\n", (res==TIMEOUT_RC)?"TIMEOUT":"ERROR"); }else{ LM_DBG("radius authentication message sent\n"); } for ( mp=sets[index2]->parsed; mp ; mp = mp->next) { vp = recv; while ( (vp=rc_avpair_get(vp, ATTRID(mp->value), VENDOR(mp->value)))!=NULL ) { memset(&pvt, 0, sizeof(pv_value_t)); if (vp->type == PW_TYPE_INTEGER) { pvt.flags = PV_VAL_INT|PV_TYPE_INT; pvt.ri = vp->lvalue; } else if (vp->type == PW_TYPE_STRING) { pvt.flags = PV_VAL_STR; pvt.rs.s = vp->strvalue; pvt.rs.len = vp->lvalue; } if (pv_set_value(msg, mp->pv, (int)EQ_T, &pvt) < 0) { LM_ERR("setting avp failed....skipping\n"); } vp = fetch_all_values ? vp->next : NULL; } } vp = recv; if (attr) for(; (vp = rc_avpair_get(vp, attr->value, 0)); vp = vp->next) extract_avp(vp); if ( res!=OK_RC && res!=BADRESP_RC) goto error; if (send) rc_avpair_free(send); if (recv) rc_avpair_free(recv); return (res==OK_RC)?1:-2; error: if (send) rc_avpair_free(send); if (recv) rc_avpair_free(recv); return -1; }
/* TODO * when timeout mechanism will be available * rc_auth_function shall be called to try another * destination if the current one has timed out * */ int resume_send_auth(int fd, struct sip_msg *msg, void *param) { int res; map_list *mp; pv_value_t pvt; struct rad_ctx *rctx; VALUE_PAIR *recv = NULL, *vp = NULL; rctx = (struct rad_ctx *)param; if (rctx == NULL) { LM_ERR("no context given\n"); return -1; } res = rc_auth_resume(&rctx->ctx, &recv); if (res == OK_RC || res == REJECT_RC) { async_status = ASYNC_DONE; } else if (res == READBLOCK_RC) { async_status = ASYNC_CONTINUE; return 1; } else { LM_ERR("radius authentication message failed with %s\n", ((res==BADRESP_RC)?"BAD REPLY":"ERROR")); goto error; } for ( mp=sets[rctx->index2]->parsed; mp ; mp = mp->next) { vp = recv; while ( (vp=rc_avpair_get(vp, ATTRID(mp->value), VENDOR(mp->value)))!=NULL ) { memset(&pvt, 0, sizeof(pv_value_t)); if (vp->type == PW_TYPE_INTEGER) { pvt.flags = PV_VAL_INT|PV_TYPE_INT; pvt.ri = vp->lvalue; } else if (vp->type == PW_TYPE_STRING) { pvt.flags = PV_VAL_STR; pvt.rs.s = vp->strvalue; pvt.rs.len = vp->lvalue; } if (pv_set_value(msg, mp->pv, (int)EQ_T, &pvt) < 0) { LM_ERR("setting avp failed....skipping\n"); } vp = fetch_all_values ? vp->next : NULL; } } vp = recv; if (attr) for(; (vp = rc_avpair_get(vp, attr->value, 0)); vp = vp->next) extract_avp(vp); if ( res!=OK_RC && res!=REJECT_RC) goto error; if (rctx->send) rc_avpair_free(rctx->send); if (recv) rc_avpair_free(recv); pkg_free(rctx); return (res==OK_RC)?1:-2; error: pkg_free(rctx); if (rctx->send) rc_avpair_free(rctx->send); if (recv) rc_avpair_free(recv); return -1; }