Beispiel #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;
}
Beispiel #2
0
/**
 * Record routes, with given user as parameter.
 * @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_record_route(struct sip_msg *msg,char *str1,char *str2)
{
	str rr={0,0};
	str u = {0,0},scheme={0,0},scscf={0,0};
	
	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 = s_record_route_s.len+scheme.len+u.len+1+scscf.len+s_record_route_e.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,s_record_route_s);
			STR_APPEND(rr,scheme);
			STR_APPEND(rr,u);
			rr.s[rr.len++]='@';
			STR_APPEND(rr,scscf);
			STR_APPEND(rr,s_record_route_e);					
	}
	
	if (cscf_add_header_first(msg,&rr,HDR_RECORDROUTE_T)) return CSCF_RETURN_TRUE;
	else{
		if (rr.s) pkg_free(rr.s);
		return CSCF_RETURN_BREAK;
	}
	
out_of_memory:
	return CSCF_RETURN_BREAK;	
}
/**
 * Creates notifications with the given content for all of the subscribers.
 * @param pv - r_public* to which it refers
 * @param cv - the r_contact* to which it refers or NULL if for all
 * @param ps - the r_subscriber*  to which it refers or NULL if for all
 * @param content - the body content
 * @param expires - the remaining subcription expiration time in seconds
 */
static void r_create_notifications(void *pv,void *cv,void *ps,str content,long expires)
{
	r_notification *n;
	r_public *p=(r_public*)pv;
//	r_contact *c;
	r_subscriber *for_s=(r_subscriber*)ps;
	r_subscriber *s;	
	str uri={0,0},req_uri={0,0},subscription_state={"active;expires=10000000000",26},
		event={0,0},content_type={"application/reginfo+xml",23};
		
	uri = p->aor;
	if (!for_s)	s = p->shead;
	else s = for_s;
	
	while(s){
		req_uri.len = s->subscriber.len+ruri_lr.len;
		req_uri.s = pkg_malloc(req_uri.len);
		if (!req_uri.s) {
			LOG(L_ERR,"ERR:"M_NAME":r_create_notifications: Error allocating %d bytes.\n",req_uri.len);
			return;			
		}
		memcpy(req_uri.s,s->subscriber.s,s->subscriber.len);
		memcpy(req_uri.s+s->subscriber.len,ruri_lr.s,ruri_lr.len);
		//route = s->path;
		if (s->expires>time_now) {
			subscription_state.s = pkg_malloc(32);
			subscription_state.len=0;
			if (subscription_state.s){
				sprintf(subscription_state.s,"%.*s%ld",subs_active.len,subs_active.s,expires);
				subscription_state.len=strlen(subscription_state.s);
			}					
		}else {					
			STR_PKG_DUP(subscription_state,subs_terminated,"pkg subs state");
		}
		n = new_r_notification(req_uri,uri,subscription_state,event,
			content_type,content,s->dialog,s->version++);						
		if (req_uri.s) pkg_free(req_uri.s);
		if (subscription_state.s) pkg_free(subscription_state.s);	
		if (n) {
			#ifdef WITH_IMS_PM
				n->is_scscf_dereg=(expires==0);
			#endif 
			add_r_notification(n);
		}		
		
		if (!for_s) s = s->next;				
		else s = 0;
	}
	return;
out_of_memory:
	if (req_uri.s) pkg_free(req_uri.s);
	return;	
}
/**
 * Enforce a response coming from a UE to contain the same Record Route headers sent in the
 * corresponding request.
 * @param msg - the SIP reply
 * @param str1 - not used
 * @param str2 - not used
 * @returns #CSCF_RETURN_TRUE on success, #CSCF_RETURN_ERROR on error
 */
int P_enforce_record_routes(struct sip_msg *msg,char *str1, char *str2)
{
	str hdr = {0,0};
	str rr_req = {0,0};
	struct sip_msg *req = cscf_get_request_from_reply(msg);

	LOG(L_INFO,"INF:"M_NAME":P_enforce_record_routes(): Enforcing RR in %d reply with the request ones\n",
			msg->first_line.u.reply.statuscode);

	if (!req){
		LOG(L_ERR,"ERR:"M_NAME":P_enforce_record_routes(): No transactional request found.\n");
		return CSCF_RETURN_ERROR;
	}
	
	if(!cscf_del_all_headers(msg, HDR_RECORDROUTE_T)){
		LOG(L_ERR,"ERR:"M_NAME":P_enforce_record_routes(): error while deleting headers\n");
		return CSCF_RETURN_ERROR;
	}
	
	rr_req = cscf_get_record_routes(req);
	if(rr_req.len){
		hdr.len = pcscf_record_route_mt.len + s_record_route_s.len + rr_req.len+s_record_route_e.len;
		if(!(hdr.s = pkg_malloc(hdr.len))){
		    LOG(L_ERR,"ERR:"M_NAME":P_enforce_record_routes(): Unable to allocate memory for hdr\n");
		    goto out_of_memory;
		}
		hdr.len = 0;
		STR_APPEND(hdr,pcscf_record_route_mt);
		STR_APPEND(hdr,s_record_route_s);
		STR_APPEND(hdr,rr_req);
		STR_APPEND(hdr,s_record_route_e);		
	}else{		
		LOG(L_ERR,"ERR:"M_NAME":P_enforce_record_routes(): Unable to get record routes - the RR should not be empty...\n");
		// still, let it continue, maybe it was empty on purpose
		//return CSCF_RETURN_ERROR;
		STR_PKG_DUP(hdr,pcscf_record_route_mt,"pkg");
	}
	
	if(!cscf_add_header_first(msg,&hdr,HDR_RECORDROUTE_T)){
		LOG(L_ERR,"ERR:"M_NAME":P_enforce_record_routes(): Unable to add header\n");
		if (hdr.s) pkg_free(hdr.s);
		return CSCF_RETURN_FALSE;
	}

	return CSCF_RETURN_TRUE;
	
out_of_memory:
	return CSCF_RETURN_ERROR;
}
Beispiel #5
0
int I_scscf_select(struct sip_msg* msg, char* str1, char* str2)
{
	str call_id,scscf_name={0,0};
	struct sip_msg *req;
	int result;
	str hdr={0,0};

	//print_scscf_list(L_ERR);
		
	call_id = cscf_get_call_id(msg,0);
	LOG(L_DBG,"DBG:"M_NAME":I_scscf_select(): <%.*s>\n",call_id.len,call_id.s);
	if (!call_id.len)
		return CSCF_RETURN_FALSE;
	
	scscf_name = take_scscf_entry(call_id);
	if (!scscf_name.len){
		I_scscf_drop(msg,str1,str2);
		cscf_reply_transactional(msg,600,MSG_600_FORWARDING_FAILED);			
		return CSCF_RETURN_BREAK;
	}
	
	if (msg->first_line.u.request.method.len==8 &&
		strncasecmp(msg->first_line.u.request.method.s,"REGISTER",8)==0) {
		/* REGISTER fwding */			
		if (str1&&str1[0]=='0'){
			/* first time */	
			//LOG(L_CRIT,"rewrite uri\n");
			if (rewrite_uri(msg, &(scscf_name)) < 0) {
				LOG(L_ERR,"ERR:"M_NAME":I_UAR_forward: Unable to Rewrite URI\n");
				result = CSCF_RETURN_FALSE;
			}else
				result = CSCF_RETURN_TRUE;
		}else{
			/* subsequent */
			//LOG(L_CRIT,"append branch\n");
			req = msg;//cscf_get_request_from_reply(msg);
			append_branch(req,scscf_name.s,scscf_name.len,0,0,0,0);
			result = CSCF_RETURN_TRUE;
		}
	}else{
		/* Another request */
		result = CSCF_RETURN_TRUE;
		
		hdr.len = route_hdr_s.len+scscf_name.len+route_hdr_e.len;
		hdr.s = pkg_malloc(hdr.len);
		if (!hdr.s){
			LOG(L_ERR,"ERR:"M_NAME":Mw_REQUEST_forward: Error allocating %d bytes\n",
				hdr.len);
			result = CSCF_RETURN_TRUE;
		}
		hdr.len=0;
		STR_APPEND(hdr,route_hdr_s);
		STR_APPEND(hdr,scscf_name);
		STR_APPEND(hdr,route_hdr_e);
	
		if (!cscf_add_header_first(msg,&hdr,HDR_ROUTE_T)){
			pkg_free(hdr.s);
			result = CSCF_RETURN_TRUE;
		}
		
		if (msg->dst_uri.s) pkg_free(msg->dst_uri.s);	
		STR_PKG_DUP(msg->dst_uri,scscf_name,"pkg");
	}

	if (scscf_name.s) shm_free(scscf_name.s);
	return result;
out_of_memory:	
	if (scscf_name.s) shm_free(scscf_name.s);
	return CSCF_RETURN_ERROR;
}
Beispiel #6
0
/**
 * Remove from <str1> headers the <str2> tag
 * \note Does not work if you call it multiple times for the same hdr_name!
 * \note Because of the note above, this needs a fix to accept multiple tags in the str2 parameter!
 * @param msg - SIP Request
 * @param str1 - the header to remove from
 * @param str2 - the tag to remove
 * @returns #CSCF_RETURN_TRUE if removed, #CSCF_RETURN_FALSE if no changes required or #CSCF_RETURN_FALSE on error
 */
int P_remove_header_tag(struct sip_msg *msg,char *str1, char *str2)
{
	str hdr_name,tag,x,y;
	struct hdr_field *hdr;
	char *c;
	int found,i,j,changed=0;
	
	hdr_name.s = str1;
	hdr_name.len = strlen(str1);

	tag.s = str2;
	tag.len = strlen(str2);
	
	hdr = cscf_get_header(msg,hdr_name);
	while (hdr){
		/* get the original body */
		x = hdr->body;
		LOG(L_INFO,"DBG:"M_NAME":P_remove_header_tag(): Original <%.*s> -> <%.*s>\n",
			hdr_name.len,hdr_name.s,x.len,x.s);
		
		/* duplicate the original body */
		x.len++;
		STR_PKG_DUP(y,x,"P_remove_header_tag");
		if (!y.s) goto error;
		y.len--;
		y.s[y.len]=0;
		
		/* look for occurences of tag and overwrite with \0 */
		found=0;
		c = strtok(y.s," \t\r\n,");
		while (c){
			if (strlen(c)==tag.len && strncasecmp(c,tag.s,tag.len)==0){
				found++;
				memset(c,0,tag.len);
			}	
			c = strtok(0," \t\r\n,");
		}
		
		/* if not found just skip to next header */
		if (!found) goto next;
				
		/* compact the remaining tags by removing the \0 */		
		for(i=0,j=0;i<y.len;i++)
			if (y.s[i]!=0){ 
				y.s[j++]=y.s[i];
			} else {
				if (j!=0) y.s[j++]=',';
				while(i+1<y.len && y.s[i+1]==0)
					i++;
			}
		y.len = j;
		if (y.s[y.len-1]==',') y.len--;

		LOG(L_INFO,"DBG:"M_NAME":P_remove_header_tag(): Modified <%.*s> -> <%.*s>\n",
			hdr_name.len,hdr_name.s,y.len,y.s);

		/* write the changes */
		if (y.len){
			/* replace just the content */
			if (!cscf_replace_string(msg,x,y)){
				LOG(L_ERR,"ERR:"M_NAME":P_remove_header_tag(): Error replacing string!\n");
				if (y.s) pkg_free(y.s);
				goto error;
			}
		}else{
			/* remove the whole header */
			if (y.s) pkg_free(y.s);
			if (!cscf_del_header(msg,hdr)){
				LOG(L_ERR,"ERR:"M_NAME":P_remove_header_tag(): Error removing the whole header!\n");
				goto error;
			}
		}
		changed++;
		
next:
		hdr = cscf_get_next_header(msg,hdr_name,hdr);
	}	

	return changed?CSCF_RETURN_TRUE:CSCF_RETURN_FALSE;
error:
out_of_memory:
	return CSCF_RETURN_ERROR;
}