int set_mod_param(char* _mod, char* _name, modparam_t _type, void* _val) { void* ptr; if (!_mod) { LOG(L_ERR, "set_mod_param(): Invalid _mod parameter value\n"); return -1; } if (!_name) { LOG(L_ERR, "set_mod_param(): Invalid _name parameter value\n"); return -2; } ptr = find_param_export(_mod, _name, _type); if (!ptr) { LOG(L_ERR, "set_mod_param(): Parameter not found\n"); return -3; } switch(_type) { case STR_PARAM: *((char**)ptr) = strdup((char*)_val); break; case INT_PARAM: *((int*)ptr) = (int)(long)_val; break; } return 0; }
/** * This callback is called on any response message in the lifespan of * the dialog. The callback is called just before the message is * copied to pkg memory so it is still mutable. * * @param did - The dialog structure. The pointer is used as an ID. * @param type - The reason for the callback. DLGCB_CONFIRMED * @param params - The sst information */ static void sst_dialog_response_fwded_CB(struct dlg_cell* did, int type, struct dlg_cb_params * params) { struct sip_msg* msg = params->msg; int *param; short info_dirty = 0; /* * This test to see if the message is a response sould ALWAYS be * true. This callback should not get called for requests. But * lets be safe. */ if (msg->first_line.type != SIP_REPLY) return; sst_msg_info_t minfo = {0,0,0,0}; sst_info_t *info = (sst_info_t *)*(params->param); sst_info_t tmp_info; LM_DBG("Dialog seen REPLY %d %.*s\n", msg->first_line.u.reply.statuscode, msg->first_line.u.reply.reason.len, msg->first_line.u.reply.reason.s); /* * Need to check to see if it is a 422 response. If it is, * make sure our Min-SE: for this dialog is set at least as * large as in the Min-SE: in the reply 422 message. If not, * we will create an INVITE, 422 loop. */ if (msg->first_line.u.reply.statuscode == 422) { if (parse_msg_for_sst_info(msg, &minfo)) { LM_ERR("failed to prase sst information for thr 422 reply\n"); return; } /* Make sure we do not try to use anything smaller */ if (info->interval < minfo.min_se) CHECK_AND_UPDATE_SST_INFO(info, interval, minfo.min_se, info_dirty); goto update_info; /* There is nothing else to do with this */ } /* * We need to get the method this reply is for from the CSEQ * body. The RFC states we can only play with 2XX from the * INVITE or reINVTE/UPDATE. */ if (!msg->cseq && ((parse_headers(msg, HDR_CSEQ_F, 0) == -1) || !msg->cseq)) { LM_ERR("failed to parse CSeq\n"); return; } /* 2XX replies to INVITES only !*/ if (msg->first_line.u.reply.statuscode > 199 && msg->first_line.u.reply.statuscode < 300 && (get_cseq(msg)->method_id == METHOD_INVITE || get_cseq(msg)->method_id == METHOD_UPDATE)) { if (parse_msg_for_sst_info(msg, &minfo)) { LM_ERR("failed to parse sst information for the 2XX reply\n"); return; } LM_DBG("parsing 200 OK response %d / %d\n", minfo.supported, minfo.se); if (info->supported != SST_UAC) { CHECK_AND_UPDATE_SST_INFO_TMP(info, supported, (minfo.supported?SST_UAS:SST_UNDF),info_dirty, tmp_info); } if (minfo.se != 0) { if (sst_interval > minfo.min_se) CHECK_AND_UPDATE_SST_INFO(info, interval, sst_interval, info_dirty); else CHECK_AND_UPDATE_SST_INFO_TMP(info, interval, MAX(minfo.se, sst_min_se), info_dirty, tmp_info); LM_DBG("UAS supports timer\n"); set_dialog_lifetime(did, info->interval); } else { /* no se header found, we want to resquest it. */ if (info->supported == SST_UAC) { char se_buf[80]; LM_DBG("UAC supports timer\n"); LM_DBG("appending the Session-Expires: header to the 2XX reply." " UAC will deal with it.\n"); /* * GOOD! we can just insert the Session-Expires: * header and forward back to the UAC and it will * deal with refreshing the session. */ if (sst_interval > minfo.min_se) CHECK_AND_UPDATE_SST_INFO(info, interval, sst_interval, info_dirty); else CHECK_AND_UPDATE_SST_INFO_TMP(info, interval, MAX(minfo.se, sst_min_se), info_dirty, tmp_info); snprintf(se_buf, 80, "Session-Expires: %d;refresher=uac\r\n", info->interval); if (append_header(msg, se_buf)) { LM_ERR("failed to append Session-Expires header\n"); return; } /* Set the dialog timeout HERE */ set_dialog_lifetime(did, info->interval); } else { /* We are sunk, uac did not request it, and it * does not support it */ LM_DBG("UAC and UAS do not support timers!" " No session timers for this session.\n"); param = find_param_export("dialog", "default_timeout", INT_PARAM); CHECK_AND_UPDATE_SST_INFO_TMP(info, interval, param?*param:12*3600, info_dirty, tmp_info); set_dialog_lifetime(did, info->interval); } } } /* End of 2XX for an INVITE */ update_info: if (info_dirty){ str raw_info = {(char*)info, sizeof(sst_info_t)}; if (dlg_binds->store_dlg_value(did, &info_val_name, &raw_info) != 0) { LM_ERR("sst_info can't be updated\n"); } } }
int set_mod_param_regex(char* regex, char* name, modparam_t type, void* val) { struct sr_module* t; regex_t preg; int mod_found, len; char* reg; void *ptr, *val2; modparam_t param_type; str s; if (!regex) { LM_ERR("Invalid mod parameter value\n"); return -5; } if (!name) { LM_ERR("Invalid name parameter value\n"); return -6; } len = strlen(regex); reg = pkg_malloc(len + 2 + 1); if (reg == 0) { LM_ERR("No memory left\n"); return -1; } reg[0] = '^'; memcpy(reg + 1, regex, len); reg[len + 1] = '$'; reg[len + 2] = '\0'; if (regcomp(&preg, reg, REG_EXTENDED | REG_NOSUB | REG_ICASE)) { LM_ERR("Error while compiling regular expression\n"); pkg_free(reg); return -2; } mod_found = 0; for(t = modules; t; t = t->next) { if (regexec(&preg, t->exports.name, 0, 0, 0) == 0) { DBG("set_mod_param_regex: '%s' matches module '%s'\n", regex, t->exports.name); mod_found = 1; /* PARAM_STR (PARAM_STRING) may be assigned also to PARAM_STRING(PARAM_STR) so let get both module param */ ptr = find_param_export(t, name, type | ((type & (PARAM_STR|PARAM_STRING))?PARAM_STR|PARAM_STRING:0), ¶m_type); if (ptr) { /* type casting */ if (type == PARAM_STRING && PARAM_TYPE_MASK(param_type) == PARAM_STR) { s.s = (char*)val; s.len = s.s ? strlen(s.s) : 0; val2 = &s; } else if (type == PARAM_STR && PARAM_TYPE_MASK(param_type) == PARAM_STRING) { s = *(str*)val; val2 = s.s; /* zero terminator expected */ } else { val2 = val; } DBG("set_mod_param_regex: found <%s> in module %s [%s]\n", name, t->exports.name, t->path); if (param_type & PARAM_USE_FUNC) { if ( ((param_func_t)(ptr))(param_type, val2) < 0) { regfree(&preg); pkg_free(reg); return -4; } } else { switch(PARAM_TYPE_MASK(param_type)) { case PARAM_STRING: *((char**)ptr) = pkg_malloc(strlen((char*)val2)+1); if (!*((char**)ptr)) { LM_ERR("No memory left\n"); regfree(&preg); pkg_free(reg); return -1; } strcpy(*((char**)ptr), (char*)val2); break; case PARAM_STR: ((str*)ptr)->s = pkg_malloc(((str*)val2)->len+1); if (!((str*)ptr)->s) { LM_ERR("No memory left\n"); regfree(&preg); pkg_free(reg); return -1; } memcpy(((str*)ptr)->s, ((str*)val2)->s, ((str*)val2)->len); ((str*)ptr)->len = ((str*)val2)->len; ((str*)ptr)->s[((str*)ptr)->len] = 0; break; case PARAM_INT: *((int*)ptr) = (int)(long)val2; break; } } } else { LM_ERR("parameter <%s> of type <%d> not found in module <%s>\n", name, type, t->exports.name); regfree(&preg); pkg_free(reg); return -3; } } } regfree(&preg); pkg_free(reg); if (!mod_found) { LM_ERR("No module matching <%s> found\n", regex); return -4; } return 0; }
static int mod_init(void) { pv_spec_t avp_spec; int *param; modparam_t type; // initialize the canonical_uri_avp structure if (canonical_uri_avp.spec.s==NULL || canonical_uri_avp.spec.len<=0) { LOG(L_ERR, "missing/empty canonical_uri_avp parameter. using default.\n"); canonical_uri_avp.spec.s = CANONICAL_URI_AVP_SPEC; } if (pv_parse_spec(&(canonical_uri_avp.spec), &avp_spec)==0 || avp_spec.type!=PVT_AVP) { LOG(L_CRIT, "invalid AVP specification for canonical_uri_avp: `%s'\n", canonical_uri_avp.spec.s); return -1; } if (pv_get_avp_name(0, &(avp_spec.pvp), &(canonical_uri_avp.name), &(canonical_uri_avp.type))!=0) { LOG(L_CRIT, "invalid AVP specification for canonical_uri_avp: `%s'\n", canonical_uri_avp.spec.s); return -1; } // initialize the signaling_ip_avp structure if (signaling_ip_avp.spec.s==NULL || signaling_ip_avp.spec.len<=0) { LOG(L_ERR, "missing/empty signaling_ip_avp parameter. using default.\n"); signaling_ip_avp.spec.s = SIGNALING_IP_AVP_SPEC; } if (pv_parse_spec(&(signaling_ip_avp.spec), &avp_spec)==0 || avp_spec.type!=PVT_AVP) { LOG(L_CRIT, "invalid AVP specification for signaling_ip_avp: `%s'\n", signaling_ip_avp.spec.s); return -1; } if (pv_get_avp_name(0, &(avp_spec.pvp), &(signaling_ip_avp.name), &(signaling_ip_avp.type))!=0) { LOG(L_CRIT, "invalid AVP specification for signaling_ip_avp: `%s'\n", signaling_ip_avp.spec.s); return -1; } // initialize the sip_application_avp structure if (sip_application_avp.spec.s==NULL || sip_application_avp.spec.len<=0) { LOG(L_ERR, "missing/empty sip_application_avp parameter. using default.\n"); sip_application_avp.spec.s = SIP_APPLICATION_AVP_SPEC; } if (pv_parse_spec(&(sip_application_avp.spec), &avp_spec)==0 || avp_spec.type!=PVT_AVP) { LOG(L_CRIT, "invalid AVP specification for sip_application_avp: `%s'\n", sip_application_avp.spec.s); return -1; } if (pv_get_avp_name(0, &(avp_spec.pvp), &(sip_application_avp.name), &(sip_application_avp.type))!=0) { LOG(L_CRIT, "invalid AVP specification for sip_application_avp: `%s'\n", sip_application_avp.spec.s); return -1; } // bind to the dialog API if (load_dlg_api(&dlg_api)!=0) { LOG(L_CRIT, "cannot load the dialog module API\n"); return -1; } // load dlg_flag and default_timeout parameters from the dialog module param = find_param_export(find_module_by_name("dialog"), "dlg_flag", INT_PARAM, &type); if (!param) { LOG(L_CRIT, "cannot find dlg_flag parameter in the dialog module\n"); return -1; } if (type != INT_PARAM) { LOG(L_CRIT, "dlg_flag parameter found but with wrong type: %d\n", type); return -1; } dialog_flag = *param; // register dialog creation callback if (dlg_api.register_dlgcb(NULL, DLGCB_CREATED, __dialog_created, NULL, NULL) != 0) { LOG(L_CRIT, "cannot register callback for dialog creation\n"); return -1; } // register dialog loading callback if (dlg_api.register_dlgcb(NULL, DLGCB_LOADED, __dialog_loaded, NULL, NULL) != 0) { LOG(L_ERR, "cannot register callback for dialogs loaded from the database\n"); } // register a pre-script callback to automatically enable dialog tracing if (register_script_cb(postprocess_request, POST_SCRIPT_CB|REQUEST_CB, 0) != 0) { LOG(L_CRIT, "ERROR:call_control:mod_init: could not register request postprocessing callback\n"); return -1; } return 0; }