Example #1
0
int pv_set_branchx_helper(sip_msg_t *msg, pv_param_t *param,
		int op, pv_value_t *val, int btype)
{
	int idx = 0;
	int idxf = 0;
	branch_t *br;
	struct socket_info *si;
	int port, proto;
	str host;
	char backup;

	if(msg==NULL || param==NULL)
	{
		LM_ERR("bad parameters\n");
		return -1;
	}

	if(btype==1) {
		br = &_pv_sbranch;
	} else {
		/* get the index */
		if(pv_get_spec_index(msg, param, &idx, &idxf)!=0)
		{
			LM_ERR("invalid index\n");
			return -1;
		}
		if(idx<0)
		{
			if((int)nr_branches + idx >= 0) {
				idx += nr_branches;
			} else {
				LM_ERR("index too low: %d (%u)\n", idx, nr_branches);
				return -1;
			}
		}
		LM_DBG("managing branch index %d (%u)\n", idx, nr_branches);
		br = get_sip_branch(idx);
	}

	if(br==NULL)
	{
		LM_DBG("no branch to operate on\n");
		return -1;
	}

	switch(param->pvn.u.isname.name.n)
	{
		case 1: /* dst uri */
			if(val==NULL || (val->flags&PV_VAL_NULL))
			{
				br->dst_uri[0] = '\0';
				br->dst_uri_len = 0;
				break;
			}
			if(!(val->flags&PV_VAL_STR))
			{
				LM_ERR("str value required to set branch dst uri\n");
				return -1;
			}
			if(val->rs.len<=0)
			{
				br->dst_uri[0] = '\0';
				br->dst_uri_len = 0;
				break;
			}

			if (unlikely(val->rs.len > MAX_URI_SIZE - 1))
			{
				LM_ERR("too long dst uri: %.*s\n",
								val->rs.len, val->rs.s);
				return -1;
			}
			memcpy(br->dst_uri, val->rs.s, val->rs.len);
			br->dst_uri[val->rs.len] = 0;
			br->dst_uri_len = val->rs.len;
		break;
		case 2: /* path */
			if(val==NULL || (val->flags&PV_VAL_NULL))
			{
				br->path[0] = '\0';
				br->path_len = 0;
				break;
			}
			if(!(val->flags&PV_VAL_STR))
			{
				LM_ERR("str value required to set branch path\n");
				return -1;
			}
			if(val->rs.len<=0)
			{
				br->path[0] = '\0';
				br->path_len = 0;
				break;
			}

			if (unlikely(val->rs.len > MAX_PATH_SIZE - 1))
			{
				LM_ERR("path too long: %.*s\n",
							val->rs.len, val->rs.s);
				return -1;
			}
			memcpy(br->path, val->rs.s, val->rs.len);
			br->path[val->rs.len] = 0;
			br->path_len = val->rs.len;
		break;
		case 3: /* Q */
			if(val==NULL || (val->flags&PV_VAL_NULL))
			{
				br->q = Q_UNSPECIFIED;
				break;
			}
			if(!(val->flags&PV_VAL_INT))
			{
				LM_ERR("int value required to set branch q\n");
				return -1;
			}
			br->q = val->ri;
		break;
		case 4: /* send socket */
			if(val==NULL || (val->flags&PV_VAL_NULL))
			{
				br->force_send_socket = NULL;
				break;
			}
			if(!(val->flags&PV_VAL_STR))
			{
				LM_ERR("str value required to set branch send sock\n");
				return -1;
			}
			if(val->rs.len<=0)
			{
				br->force_send_socket = NULL;
				break;
			}
			backup = val->rs.s[val->rs.len];
			val->rs.s[val->rs.len] = '\0';
			if (parse_phostport(val->rs.s, &host.s, &host.len, &port,
						&proto) < 0)
			{
				LM_ERR("invalid socket specification\n");
				val->rs.s[val->rs.len] = backup;
				return -1;
			}
			val->rs.s[val->rs.len] = backup;
			si = grep_sock_info(&host, (unsigned short)port,
					(unsigned short)proto);
			if (si!=NULL)
			{
				br->force_send_socket = si;
			} else {
				LM_WARN("no socket found to match [%.*s]\n",
					val->rs.len, val->rs.s);
				br->force_send_socket = NULL;
			}
		break;
		case 5: /* count */
			/* do nothing - cannot set the branch counter */
		break;
		case 6: /* flags */
			if(val==NULL || (val->flags&PV_VAL_NULL))
			{
				br->flags = 0;
				break;
			}
			if(!(val->flags&PV_VAL_INT))
			{
				LM_ERR("int value required to set branch flags\n");
				return -1;
			}
			br->flags = val->ri;
		break;
		case 7: /* ruid */
			/* do nothing - cannot set the ruid */
		break;
		case 8: /* location_ua */
			/* do nothing - cannot set the location_ua */
		break;
		default:
			/* 0 - uri */
			if(val==NULL || (val->flags&PV_VAL_NULL))
			{
				if(btype==1) {
					memset(br, 0, sizeof(branch_t));
				} else {
					drop_sip_branch(idx);
				}
			} else {
				if(!(val->flags&PV_VAL_STR))
				{
					LM_ERR("str value required to set branch uri\n");
					return -1;
				}
				if(val->rs.len<=0)
				{
					if(btype==1) {
						memset(br, 0, sizeof(branch_t));
					} else {
						drop_sip_branch(idx);
					}
				} else {
					if (unlikely(val->rs.len > MAX_URI_SIZE - 1))
					{
						LM_ERR("too long r-uri: %.*s\n",
								val->rs.len, val->rs.s);
						return -1;
					}
					memcpy(br->uri, val->rs.s, val->rs.len);
					br->uri[val->rs.len] = 0;
					br->len = val->rs.len;
				}
			}
	}

	return 0;
}
Example #2
0
int pv_get_branchx_helper(sip_msg_t *msg, pv_param_t *param,
		pv_value_t *res, int btype)
{
	int idx = 0;
	int idxf = 0;
	branch_t *br;

	if(btype==1) {
		br = &_pv_sbranch;
	} else {
		/* get the index */
		if(pv_get_spec_index(msg, param, &idx, &idxf)!=0)
		{
			LM_ERR("invalid index\n");
			return pv_get_null(msg, param, res);
		}
		br = get_sip_branch(idx);
		if(br==NULL) {
			return pv_get_null(msg, param, res);
		}
	}

	/* branch(count) doesn't need a valid branch, everything else does */
	if(br->len == 0 && ( param->pvn.u.isname.name.n != 5/* count*/ ))
	{
		LM_ERR("error accessing branch [%d]\n", idx);
		return pv_get_null(msg, param, res);
	}

	switch(param->pvn.u.isname.name.n)
	{
		case 1: /* dst uri */
			if(br->dst_uri_len==0)
				return pv_get_null(msg, param, res);
			return pv_get_strlval(msg, param, res, br->dst_uri, br->dst_uri_len);
		case 2: /* path */
			if(br->path_len==0)
				return pv_get_null(msg, param, res);
			return pv_get_strlval(msg, param, res, br->path, br->path_len);
		case 3: /* Q */
			if(br->q == Q_UNSPECIFIED)
				return pv_get_null(msg, param, res);
			return pv_get_sintval(msg, param, res, br->q);
		case 4: /* send socket */
			if(br->force_send_socket!=0)
				return pv_get_strval(msg, param, res, &br->force_send_socket->sock_str);
			return pv_get_null(msg, param, res);
		case 5: /* count */
			return pv_get_uintval(msg, param, res, nr_branches);
		case 6: /* flags */
			return pv_get_uintval(msg, param, res, br->flags);
		case 7: /* ruid */
			if(br->ruid_len==0)
				return pv_get_null(msg, param, res);
			return pv_get_strlval(msg, param, res, br->ruid, br->ruid_len);
		case 8: /* location_ua */
			if(br->location_ua_len==0)
				return pv_get_null(msg, param, res);
			return pv_get_strlval(msg, param, res, br->location_ua, br->location_ua_len);
		default:
			/* 0 - uri */
			return pv_get_strlval(msg, param, res, br->uri, br->len);
	}

	return 0;
}
Example #3
0
/*! \brief
 * Lookup contacts in the database for all branches, including R-URI
 * \return: -1 : not found
 *          -2 : found but method not allowed (for r-uri)
 *          -3 : error
 */
int lookup_branches(sip_msg_t *msg, udomain_t *d)
{
	unsigned int nr_branches_start;
	unsigned int i;
	int ret;
	int found;
	str new_uri;
	str ruri_b_uri = {0};
	str ruri_b_dst_uri = {0};
	str ruri_b_path = {0};
	int ruri_b_q = Q_UNSPECIFIED;
	struct socket_info *ruri_b_socket = 0;
	flag_t ruri_b_flags = 0;
	str ruri_b_instance = {0};
	unsigned int ruri_b_reg_id = 0;
	str ruri_b_ruid = {0};
	str ruri_b_ua = {0};
	branch_t *crt = NULL;

	ret = 1;
	found  = 0;
	nr_branches_start = nr_branches;
	/* first lookup the r-uri */
	ret = lookup(msg, d, NULL);

	/* if no other branches -- all done */
	if(nr_branches_start==0)
		return ret;

	if(ret>0)
		found = 1;

	/* backup r-uri branch */
	ruri_b_uri = msg->new_uri;
	ruri_b_dst_uri = msg->dst_uri;
	ruri_b_path = msg->path_vec;
	ruri_b_q = get_ruri_q();
	ruri_b_socket = msg->force_send_socket;
	getbflagsval(0, &ruri_b_flags);
	ruri_b_instance = msg->instance;
	ruri_b_reg_id = msg->reg_id;
	ruri_b_ruid = msg->ruid;
	ruri_b_ua = msg->location_ua;
	reset_ruri_branch(msg);
	/* set new uri buf to null, otherwise is freed or overwritten by
	 * rewrite_uri() during branch lookup */
	msg->new_uri.len=0;
	msg->new_uri.s=0;
	msg->parsed_uri_ok=0;

	for(i=0; i<nr_branches_start; i++) {
		crt = get_sip_branch(i);
		/* it has to be a clean branch to do lookup for it */
		if(crt->len <= 0 || crt->dst_uri_len > 0
				|| crt->path_len > 0 || crt->force_send_socket!=NULL
				|| crt->flags !=0)
			continue;
		/* set the new uri from branch and lookup */
		new_uri.s = crt->uri;
		new_uri.len = crt->len;
		if (rewrite_uri(msg, &new_uri) < 0) {
			LM_ERR("unable to rewrite Request-URI for branch %u\n", i);
			ret = -3;
			goto done;
		}
		ret = lookup(msg, d, NULL);
		if(ret>0) {
			/* move r-uri branch attributes to crt branch */
			found = 1;

			if (unlikely(msg->new_uri.len > MAX_URI_SIZE - 1)) {
				LM_ERR("too long uri: %.*s\n", msg->new_uri.len,
						msg->new_uri.s);
				ret = -3;
				goto done;
			}

			/* copy the dst_uri */
			if (msg->dst_uri.len>0 && msg->dst_uri.s!=NULL) {
				if (unlikely(msg->dst_uri.len > MAX_URI_SIZE - 1)) {
					LM_ERR("too long dst_uri: %.*s\n", msg->dst_uri.len,
							msg->dst_uri.s);
					ret = -3;
					goto done;
				}

				memcpy(crt->dst_uri, msg->dst_uri.s, msg->dst_uri.len);
				crt->dst_uri[msg->dst_uri.len] = 0;
				crt->dst_uri_len = msg->dst_uri.len;
			}

			/* copy the path string */
			if (unlikely(msg->path_vec.len>0 && msg->path_vec.s!=NULL)) {
				if (unlikely(msg->path_vec.len > MAX_PATH_SIZE - 1)) {
					LM_ERR("too long path: %.*s\n", msg->path_vec.len,
							msg->path_vec.s);
					ret = -3;
					goto done;
				}
				memcpy(crt->path, msg->path_vec.s, msg->path_vec.len);
				crt->path[msg->path_vec.len] = 0;
				crt->path_len = msg->path_vec.len;
			}

			/* copy the ruri */
			memcpy(crt->uri, msg->new_uri.s, msg->new_uri.len);
			crt->uri[msg->new_uri.len] = 0;
			crt->len = msg->new_uri.len;
			crt->q = get_ruri_q();

			crt->force_send_socket = msg->force_send_socket;
			getbflagsval(0, &crt->flags);
		}
		reset_ruri_branch(msg);
	}

done:
	reset_ruri_branch(msg);
	/* new uri could be set to allocated buffer by branch lookup */
	if(msg->new_uri.s!=NULL)
		pkg_free(msg->new_uri.s);
	msg->new_uri = ruri_b_uri;
	ruri_mark_new();
	msg->parsed_uri_ok = 0;
	msg->dst_uri = ruri_b_dst_uri;
	msg->path_vec = ruri_b_path;
	set_ruri_q(ruri_b_q);
	set_force_socket(msg, ruri_b_socket);
	setbflagsval(0, ruri_b_flags);
	msg->instance = ruri_b_instance;
	msg->reg_id = ruri_b_reg_id;
	msg->ruid = ruri_b_ruid;
	msg->location_ua = ruri_b_ua;

	return (found)?1:ret;
}