Exemple #1
0
/**
 * Check if we already did record-route
 * @param msg - the SIP message to add to
 * @param str1 - direction - "orig" or "term"
 * @param str2 - not used
 * @returns #CSCF_RETURN_TRUE if ok, #CSCF_RETURN_FALSE if not or #CSCF_RETURN_BREAK on error
 */
int S_is_record_routed(struct sip_msg *msg,char *str1,char *str2)
{
	str rr;
	str u = {0,0},scheme={0,0},scscf={0,0};
	struct hdr_field *hdr=0;
	rr_t *rr_s;
	
	enum s_dialog_direction dir = get_dialog_direction(str1);
	
	switch (dir){
		case DLG_MOBILE_ORIGINATING:
			STR_PKG_DUP(rr,scscf_record_route_mo,"pkg");
			break;
		case DLG_MOBILE_TERMINATING:
			STR_PKG_DUP(rr,scscf_record_route_mt,"pkg");
			break;
		default:
			u.s = str1;
			u.len = strlen(str1);
			if (scscf_name_str.len>4 &&
				strncasecmp(scscf_name_str.s,"sip:",4)==0){
				scheme.s = scscf_name_str.s;
				scheme.len = 4;
			}else if (scscf_name_str.len>5 &&
				strncasecmp(scscf_name_str.s,"sips:",5)==0){
				scheme.s = scscf_name_str.s;
				scheme.len = 4;
			}
			scscf.s = scheme.s+scheme.len;
			scscf.len = scscf_name_str.len - scheme.len;
			
			rr.len = scheme.len+u.len+1+scscf.len;
			rr.s = pkg_malloc(rr.len);
			if (!rr.s){
				LOG(L_ERR,"ERR:"M_NAME":S_record_route: error allocating %d bytes!\n",rr.len);	
				return CSCF_RETURN_BREAK;
			}
			rr.len = 0;
			STR_APPEND(rr,scheme);
			STR_APPEND(rr,u);
			rr.s[rr.len++]='@';
			STR_APPEND(rr,scscf);
	}

	for(hdr = cscf_get_next_record_route(msg,(struct hdr_field*) 0); hdr ; hdr = cscf_get_next_record_route(msg,hdr)){
		for (rr_s = (rr_t *)hdr->parsed;rr_s; rr_s = rr_s->next)
			if (rr_s->nameaddr.uri.len == rr.len &&
				strncasecmp(rr_s->nameaddr.uri.s,rr.s,rr.len)==0){
					pkg_free(rr.s);
					return CSCF_RETURN_TRUE;
				}
	}

	pkg_free(rr.s);
	return CSCF_RETURN_FALSE;
out_of_memory:
	return CSCF_RETURN_ERROR;
}
Exemple #2
0
/**
 * Save the Record-routes for a dialog.
 * @param msg - the SIP message to extract RRs from
 * @param str1 - the direction to know if to reverse the RR list or not
 * @param d - dialog to save to
 */
void save_dialog_routes(struct sip_msg* msg, char* str1,p_dialog *d)
{
	int i;
	rr_t *rr,*ri;	
	struct hdr_field *hdr;
	if (d->routes){
		for(i=0;i<d->routes_cnt;i++)
			shm_free(d->routes[i].s);
		shm_free(d->routes);
		d->routes = 0;
	}
	d->routes_cnt = 0;
	for(hdr=cscf_get_next_record_route(msg,0);hdr;hdr=cscf_get_next_record_route(msg,hdr)){
		rr = (rr_t*)hdr->parsed;
		for(ri=rr;ri;ri=ri->next)
			d->routes_cnt++;
	}
	d->routes = shm_malloc(sizeof(str)*d->routes_cnt);
	if (!d->routes){
		LOG(L_ERR,"ERR:"M_NAME":save_dialog_routes(): Unable to alloc %d bytes\n",
			sizeof(str)*d->routes_cnt);
		d->routes_cnt = 0;
		return;		
	}
	if (!str1) return;
	if (str1[0]=='o'||str1[0]=='0'||str1[0]=='O'){
		/* originating - reverse order */
		i = d->routes_cnt-1;
		for(hdr=cscf_get_next_record_route(msg,0);hdr;hdr=cscf_get_next_record_route(msg,hdr)){
			rr = (rr_t*)hdr->parsed;
			for(ri=rr;ri;ri=ri->next){
				STR_SHM_DUP(d->routes[i],ri->nameaddr.uri,"shm");
				i--;
			}
		}
	}else{
		/* terminating - normal order */
		i = 0;
		for(hdr=cscf_get_next_record_route(msg,0);hdr;hdr=cscf_get_next_record_route(msg,hdr)){
			rr = (rr_t*)hdr->parsed;
			for(ri=rr;ri;ri=ri->next){
				STR_SHM_DUP(d->routes[i],ri->nameaddr.uri,"shm");
				i++;
			}
		}
	}		
out_of_memory:
	return;	
}
/**
 * Checks if a response on the MT side includes all the required Record Routes, as present in the request
 * @param msg - the SIP reply to check
 * @param str1 - not used
 * @param str2 - not used
 * @return #CSCF_RETURN_TRUE on match, #CSCF_RETURN_FALSE if not matching 
 */
int P_follows_record_routes(struct sip_msg *msg, char *str1, char *str2)
{
	struct hdr_field *temp_hdr_req = NULL,*temp_hdr_rpl = NULL;
	struct sip_msg * req = NULL; 
	rr_t * rr_req = NULL, *rr_req_i = NULL;
	rr_t * rr_rpl = NULL;
  
	LOG(L_INFO,"INF:"M_NAME":P_follows_record_routes(): Checking if RR in %d reply match the request ones\n",
			msg->first_line.u.reply.statuscode);
	
	// Get the first RR in reply
	temp_hdr_rpl = cscf_get_next_record_route(msg,temp_hdr_rpl);	
	if (!temp_hdr_rpl || !(rr_rpl = (rr_t*)temp_hdr_rpl->parsed)){
		LOG(L_ERR,"ERR:"M_NAME":P_follows_record_routes(): No RR's found in reply.\n");
		goto nok;
	}
	
	// Checking first RR - this is a special case because the saved request does not include it
	if (pcscf_record_route_mt_uri.len != rr_rpl->nameaddr.uri.len || 
		strncmp(pcscf_record_route_mt_uri.s,rr_rpl->nameaddr.uri.s,pcscf_record_route_mt_uri.len)!=0){
		LOG(L_ERR,"ERR:"M_NAME":P_follows_record_routes(): First RR did not match P-CSCF MT = %.*s , Rpl = %.*s \n",
				pcscf_record_route_mt_uri.len,pcscf_record_route_mt_uri.s,rr_rpl->nameaddr.uri.len,rr_rpl->nameaddr.uri.s);
		goto nok;
	}	
	rr_rpl = rr_rpl->next;
	if (!rr_rpl){
		temp_hdr_rpl = cscf_get_next_record_route(msg,temp_hdr_rpl);	
		if (temp_hdr_rpl) 
			rr_rpl = (rr_t*)temp_hdr_rpl->parsed;
	}
	
	// Find the request
	if(!(req = cscf_get_request_from_reply(msg))) {
		LOG(L_ERR,"ERR:"M_NAME":P_follows_record_routes(): No transactional request found.\n");
		goto nok;
	}	
	temp_hdr_req = cscf_get_next_record_route(req,temp_hdr_req);	
	if (temp_hdr_req) {
		rr_req = (rr_t*)temp_hdr_req->parsed;
		rr_req_i = rr_req;
	}
	
	// Cycle through the request/reply headers and compare
	while(rr_rpl && rr_req_i) {
		
		if(rr_req_i->nameaddr.uri.len != rr_rpl->nameaddr.uri.len ||
				strncmp(rr_req_i->nameaddr.uri.s,rr_rpl->nameaddr.uri.s,rr_req_i->nameaddr.uri.len)!=0){
			LOG(L_ERR,"ERR:"M_NAME":P_follows_record_routes(): Mismatch in RR URIs Req = %.*s , Rpl = %.*s \n",
					rr_req_i->nameaddr.uri.len,rr_req_i->nameaddr.uri.s,rr_rpl->nameaddr.uri.len,rr_rpl->nameaddr.uri.s);
			goto nok;
		}
		
		rr_rpl = rr_rpl->next;
		if (!rr_rpl){
			temp_hdr_rpl = cscf_get_next_record_route(msg,temp_hdr_rpl);	
			if (temp_hdr_rpl)
				rr_rpl = (rr_t*)temp_hdr_rpl->parsed;
		}

		rr_req_i = rr_req_i->next;		
		if (!rr_req_i){
			if (rr_req){
				free_rr(&rr_req);
				temp_hdr_req->parsed = NULL;
			}
			temp_hdr_req = cscf_get_next_record_route(req,temp_hdr_req);	
			if (temp_hdr_req) {
				rr_req = (rr_t*)temp_hdr_req->parsed;
				rr_req_i = rr_req;
			}
		}
	}

	if(rr_rpl){
		LOG(L_ERR,"ERR:"M_NAME":P_follows_record_routes(): More RR headers in reply than in request\n");
		goto nok;
	}

	if(rr_req){
		LOG(L_ERR,"ERR:"M_NAME":P_follows_record_routes(): More RR headers in request than in reply\n");
		goto nok;
	}

	if (rr_req){
		free_rr(&rr_req);
		temp_hdr_req->parsed = NULL;
	}
	return CSCF_RETURN_TRUE;
	
nok:
	if (rr_req){
		free_rr(&rr_req);
		temp_hdr_req->parsed = NULL;
	}
	return CSCF_RETURN_FALSE;
}