Esempio n. 1
0
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;
}
Esempio n. 2
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");
		}
	}
}
Esempio n. 3
0
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), &param_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;
}
Esempio n. 4
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;
}