Ejemplo n.º 1
0
/* Compare 2 SIP URIs according to RFC 3261
 *
 * Return value : 0 if URIs match
 *				  1 if URIs don't match
 *				 -1 if errors have occured
 */
int compare_uris(str *raw_uri_a,struct sip_uri* parsed_uri_a,
					str *raw_uri_b,struct sip_uri *parsed_uri_b)
{
	#define UNESCAPED_BUF_LEN 1024
	char unescaped_a[UNESCAPED_BUF_LEN], unescaped_b[UNESCAPED_BUF_LEN];

	str unescaped_userA={unescaped_a, UNESCAPED_BUF_LEN};
	str unescaped_userB={unescaped_b, UNESCAPED_BUF_LEN};

	struct sip_uri first;
	struct sip_uri second;
	char matched[URI_MAX_U_PARAMS];
	int i,j;

	if ( (!raw_uri_a && !parsed_uri_a) || (!raw_uri_b && !parsed_uri_b) )
	{
		LM_ERR("Provide either a raw or parsed form of a SIP URI\n");
		return -1;
	}

	if (raw_uri_a && raw_uri_b)
	{

		/* maybe we're lucky and straight-forward comparison succeeds */
		if (raw_uri_a->len == raw_uri_b->len)
			if (strncasecmp(raw_uri_a->s,raw_uri_b->s,raw_uri_a->len) == 0)
			{
				LM_DBG("straight-forward URI match\n");
				return 0;
			}
	}

	/* XXX - maybe if we have two parsed sip_uris,
	 * or only one parsed and one raw,
	 * it should be possible to do a straight-forward
	 * URI match ? */

	if (parsed_uri_a)
		first = *parsed_uri_a;
	else
	{
		if (parse_uri(raw_uri_a->s,raw_uri_a->len,&first) < 0)
		{
			LM_ERR("Failed to parse first URI\n");
			return -1;
		}
	}

	if (parsed_uri_b)
		second = *parsed_uri_b;
	else
	{
		if (parse_uri(raw_uri_b->s,raw_uri_b->len,&second) < 0)
		{
			LM_ERR("Failed to parse second URI\n");
			return -1;
		}
	}

	if (first.type != second.type)
	{
		LM_DBG("Different uri types\n");
		return 1;
	}

	if (unescape_user(&first.user, &unescaped_userA) < 0 ||
			unescape_user(&second.user, &unescaped_userB) < 0) {
		LM_ERR("Failed to unescape user!\n");
		return -1;
	}

	first.user = unescaped_userA;
	second.user = unescaped_userB;

	compare_uri_val(user,strncmp);
	compare_uri_val(passwd,strncmp);
	compare_uri_val(host,strncasecmp);
	compare_uri_val(port,strncmp);

	compare_uri_val(transport_val,strncasecmp);
	compare_uri_val(ttl_val,strncasecmp);
	compare_uri_val(user_param_val,strncasecmp);
	compare_uri_val(maddr_val,strncasecmp);
	compare_uri_val(method_val,strncasecmp);
	compare_uri_val(lr_val,strncasecmp);
	compare_uri_val(r2_val,strncasecmp);

	if (first.u_params_no == 0 || second.u_params_no == 0)
		/* one URI doesn't have other params,
		 * automatically all unknown params in other URI match
		 */
		goto headers_check;

	memset(matched,0,URI_MAX_U_PARAMS);

	for (i=0;i<first.u_params_no;i++)
		for (j=0;j<second.u_params_no;j++)
			if (matched[j] == 0 &&
				(first.u_name[i].len == second.u_name[j].len &&
                strncasecmp(first.u_name[i].s,second.u_name[j].s,
							first.u_name[i].len) == 0))
				{
                    /* point of no return - matching unknown parameter values */
					if (first.u_val[i].len != second.u_val[j].len)
					{
						LM_DBG("Different URI param value for param %.*s\n",
								first.u_name[i].len,first.u_name[i].s);
						return 1;
					}
					else
					{
						if (first.u_val[i].len == 0)
						{
							/* no value for unknown params - match */
							matched[j] = 1;
							break;
						}

						if (strncasecmp(first.u_val[i].s,second.u_val[j].s,
							second.u_val[j].len))
						{
							LM_DBG("Different URI param value for param %.*s\n",
								first.u_name[i].len,first.u_name[i].s);
							return 1;
						}
						else
						{
							matched[j] = 1;
							break;
						}
					}
				}

	/* got here, it means all unknown params in first URI have been resolved
		=> first URI matched second URI, and the other way around
	*/

headers_check:
	 /* XXX Do we really care ? */
	compare_uri_val(headers,strncasecmp);
	return 0;
}
Ejemplo n.º 2
0
int unescape_param(str *sin, str *sout)
{
	return unescape_user(sin, sout);
}
Ejemplo n.º 3
0
/*! \brief
 * Combines all Path HF bodies into one string.
 */
int build_path_vector(struct sip_msg *_m, str *path, str *received)
{
	static char buf[MAX_PATH_SIZE];
	static char uri_buf[MAX_URI_SIZE];
	static str uri_str;
	char *p;
	struct hdr_field *hdr;
	struct sip_uri puri;

	rr_t *route = 0;

	path->len = 0;
	path->s = 0;
	received->s = 0;
	received->len = 0;

	if(parse_headers(_m, HDR_EOH_F, 0) < 0) {
		LM_ERR("failed to parse the message\n");
		goto error;
	}

	for( hdr=_m->path,p=buf ; hdr ; hdr = next_sibling_hdr(hdr)) {
		/* check for max. Path length */
		if( p-buf+hdr->body.len+1 >= MAX_PATH_SIZE) {
			LM_ERR("Overall Path body exceeds max. length of %d\n",
					MAX_PATH_SIZE);
			goto error;
		}
		if(p!=buf)
			*(p++) = ',';
		memcpy( p, hdr->body.s, hdr->body.len);
		p +=  hdr->body.len;
	}

	if (p!=buf) {
		/* check if next hop is a loose router */
		if (parse_rr_body( buf, p-buf, &route) < 0) {
			LM_ERR("failed to parse Path body, no head found\n");
			goto error;
		}
		if (parse_uri(route->nameaddr.uri.s,route->nameaddr.uri.len,&puri)<0){
			LM_ERR("failed to parse the first Path URI\n");
			goto error;
		}
		if (!puri.lr.s) {
			LM_ERR("first Path URI is not a loose-router, not supported\n");
			goto error;
		}
		if (path_use_params) {
			param_hooks_t hooks;
			param_t *params;

			if (parse_params(&(puri.params),CLASS_CONTACT,&hooks,&params)!=0){
				LM_ERR("failed to parse parameters of first hop\n");
				goto error;
			}
			/* Not interested in param body - just the hooks */
			free_params(params);

			if (hooks.contact.received) {
				uri_str.s = uri_buf;
				uri_str.len = MAX_URI_SIZE;
				if (unescape_user(&(hooks.contact.received->body), &uri_str) < 0) {
					LM_ERR("unescaping received failed\n");
					goto error;
				}
				*received = uri_str;
				LM_DBG("received is <%.*s>\n", received->len, received->s);
			}
		}
		free_rr(&route);
	}

	path->s = buf;
	path->len = p-buf;
	LM_DBG("path is <%.*s>\n", path->len, path->s);
	return 0;
error:
	if(route) free_rr(&route);
	return -1;
}