/* 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; }
int unescape_param(str *sin, str *sout) { return unescape_user(sin, sout); }
/*! \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,¶ms)!=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; }