Esempio n. 1
0
int w_is_first_hop(sip_msg_t *msg, char *p1, char *p2)
{
	int ret;
	rr_t* r = NULL;
	sip_uri_t puri;
	struct ip_addr *ip;

	if(msg==NULL)
		return -1;

	if(msg->first_line.type == SIP_REQUEST) {
		if (parse_headers( msg, HDR_VIA2_F, 0 )<0
				|| (msg->via2==0) || (msg->via2->error!=PARSE_OK))
		{
			/* sip request: if more than one via, then not first hop */
			/* no second via or error */
			LM_DBG("no 2nd via found - first hop\n");
			return 1;
		}
		return -1;
	} else if(msg->first_line.type == SIP_REPLY) {
		/* sip reply: if top record-route is myself
		 * and not received from myself (loop), then is first hop */
		if (parse_headers( msg, HDR_EOH_F, 0 )<0) {
			LM_DBG("error parsing headers\n");
			return -1;
		}
		if(msg->record_route==NULL) {
			LM_DBG("no record-route header - first hop\n");
			return 1;
		}
		if(parse_rr(msg->record_route)<0) {
			LM_DBG("failed to parse first record-route header\n");
			return -1;
		}
		r = (rr_t*)msg->record_route->parsed;
		if(parse_uri(r->nameaddr.uri.s, r->nameaddr.uri.len, &puri)<0) {
			LM_DBG("failed to parse uri in first record-route header\n");
			return -1;
		}
		if (((ip = str2ip(&(puri.host))) == NULL)
				&& ((ip = str2ip6(&(puri.host))) == NULL)) {
			LM_DBG("uri host is not an ip address\n");
			return -1;
		}
		ret = check_self(&puri.host, (puri.port.s)?puri.port_no:0,
				(puri.transport_val.s)?puri.proto:0);
		if(ret!=1) {
			LM_DBG("top record route uri is not myself\n");
			return -1;
		}
		if (ip_addr_cmp(ip, &(msg->rcv.src_ip))
				&& ((msg->rcv.src_port == puri.port_no)
					|| ((puri.port.len == 0) && (msg->rcv.src_port == 5060)))
				&& (puri.proto==msg->rcv.proto
					|| (puri.proto==0 && msg->rcv.proto==PROTO_UDP)) ) {
			LM_DBG("source address matches top record route uri - loop\n");
			return -1;
		}
		/* todo - check spirals */
		return 1;
	} else {
		return -1;
	}
}
Esempio n. 2
0
/* Returns 0 - nothing found
 *         1  - T found
 */
int t_reply_matching( struct sip_msg *p_msg , int *p_branch )
{
	struct cell*  p_cell;
	unsigned int hash_index   = 0;
	unsigned int entry_label  = 0;
	unsigned int branch_id    = 0;
	char  *hashi, *branchi, *p, *n;
	int hashl, branchl;
	int scan_space;
	str cseq_method;
	str req_method;

	char *loopi;
	int loopl;
	char *syni;
	int synl;
	
	short is_cancel;

	/* make compiler warnings happy */
	loopi=0;
	loopl=0;
	syni=0;
	synl=0;

	/* split the branch into pieces: loop_detection_check(ignored),
	 hash_table_id, synonym_id, branch_id */

	if (!(p_msg->via1 && p_msg->via1->branch && p_msg->via1->branch->value.s))
		goto nomatch2;

	/* we do RFC 3261 tid matching and want to see first if there is
	 * magic cookie in branch */
	if (p_msg->via1->branch->value.len<=MCOOKIE_LEN)
		goto nomatch2;
	if (memcmp(p_msg->via1->branch->value.s, MCOOKIE, MCOOKIE_LEN)!=0)
		goto nomatch2;

	p=p_msg->via1->branch->value.s+MCOOKIE_LEN;
	scan_space=p_msg->via1->branch->value.len-MCOOKIE_LEN;


	/* hash_id */
	n=eat_token2_end( p, p+scan_space, BRANCH_SEPARATOR);
	hashl=n-p;
	scan_space-=hashl;
	if (!hashl || scan_space<2 || *n!=BRANCH_SEPARATOR) goto nomatch2;
	hashi=p;
	p=n+1;scan_space--;

	if (!syn_branch) {
		/* md5 value */
		n=eat_token2_end( p, p+scan_space, BRANCH_SEPARATOR );
		loopl = n-p;
		scan_space-= loopl;
		if (n==p || scan_space<2 || *n!=BRANCH_SEPARATOR) 
			goto nomatch2;
		loopi=p;
		p=n+1; scan_space--;
	} else {
		/* synonym id */
		n=eat_token2_end( p, p+scan_space, BRANCH_SEPARATOR);
		synl=n-p;
		scan_space-=synl;
		if (!synl || scan_space<2 || *n!=BRANCH_SEPARATOR) 
			goto nomatch2;
		syni=p;
		p=n+1;scan_space--;
	}

	/* branch id  -  should exceed the scan_space */
	n=eat_token_end( p, p+scan_space );
	branchl=n-p;
	if (!branchl ) goto nomatch2;
	branchi=p;

	/* sanity check */
	if (reverse_hex2int(hashi, hashl, &hash_index)<0
		||hash_index>=TABLE_ENTRIES
		|| reverse_hex2int(branchi, branchl, &branch_id)<0
		||branch_id>=MAX_BRANCHES
		|| (syn_branch ? (reverse_hex2int(syni, synl, &entry_label))<0 
			: loopl!=MD5_LEN )
	) {
		DBG("DEBUG: t_reply_matching: poor reply labels %d label %d "
			"branch %d\n", hash_index, entry_label, branch_id );
		goto nomatch2;
	}


	DBG("DEBUG: t_reply_matching: hash %d label %d branch %d\n",
		hash_index, entry_label, branch_id );


	/* search the hash table list at entry 'hash_index'; lock the
	   entry first 
	*/
	cseq_method=get_cseq(p_msg)->method;
	is_cancel=cseq_method.len==CANCEL_LEN 
		&& memcmp(cseq_method.s, CANCEL, CANCEL_LEN)==0;
	LOCK_HASH(hash_index);
	for (p_cell = get_tm_table()->entrys[hash_index].first_cell; p_cell; 
		p_cell=p_cell->next_cell) {

		/* first look if branch matches */

		if (syn_branch) {
			if (p_cell->label != entry_label) 
				continue;
		} else {
			if ( memcmp(p_cell->md5, loopi,MD5_LEN)!=0)
					continue;
		}

		/* sanity check ... too high branch ? */
		if ( branch_id>=p_cell->nr_of_outgoings )
			continue;

		/* does method match ? (remember -- CANCELs have the same branch
		   as canceled transactions) */
		req_method=p_cell->method;
		if ( /* method match */
			! ((cseq_method.len==req_method.len 
			&& memcmp( cseq_method.s, req_method.s, cseq_method.len )==0)
			/* or it is a local cancel */
			|| (is_cancel && is_invite(p_cell)
				/* commented out -- should_cancel_branch set it to
				   BUSY_BUFFER to avoid collisions with replies;
				   thus, we test here by buffer size
				*/
				/* && p_cell->uac[branch_id].local_cancel.buffer ))) */
				&& p_cell->uac[branch_id].local_cancel.buffer_len ))) 
			continue;


		/* we passed all disqualifying factors .... the transaction has been
		   matched !
		*/
		set_t(p_cell);
		*p_branch =(int) branch_id;
		REF_UNSAFE( T );
		UNLOCK_HASH(hash_index);
		DBG("DEBUG: t_reply_matching: reply matched (T=%p)!\n",T);
		/* if this is a 200 for INVITE, we will wish to store to-tags to be
		 * able to distinguish retransmissions later and not to call
 		 * TMCB_RESPONSE_OUT uselessly; we do it only if callbacks are
		 * enabled -- except callback customers, nobody cares about 
		 * retransmissions of multiple 200/INV or ACK/200s
		 */
		if (is_invite(p_cell) && p_msg->REPLY_STATUS>=200 
		&& p_msg->REPLY_STATUS<300 
		&& ( (!is_local(p_cell) &&
				has_tran_tmcbs(p_cell,TMCB_RESPONSE_OUT|TMCB_E2EACK_IN) )
			|| (is_local(p_cell)&&has_tran_tmcbs(p_cell,TMCB_LOCAL_COMPLETED))
		)) {
			if (parse_headers(p_msg, HDR_TO_F, 0)==-1) {
				LOG(L_ERR, "ERROR: t_reply_matching: to parsing failed\n");
			}
		}
		if (!is_local(p_cell)) {
			run_trans_callbacks( TMCB_RESPONSE_IN, T, T->uas.request, p_msg,
				p_msg->REPLY_STATUS);
		}
		return 1;
	} /* for cycle */

	/* nothing found */
	UNLOCK_HASH(hash_index);
	DBG("DEBUG: t_reply_matching: no matching transaction exists\n");

nomatch2:
	DBG("DEBUG: t_reply_matching: failure to match a transaction\n");
	*p_branch = -1;
	set_t(0);
	return -1;
}
Esempio n. 3
0
/**
 * extract the node list from the body of a notification request SIP message
 * the SIP request will look something like:
 * 	KDMQ sip:10.0.0.0:5062
 * 	To: ...
 * 	From: ...
 * 	Max-Forwards: ...
 * 	Content-Length: 22
 * 	
 * 	sip:host1:port1;param1=value1
 * 	sip:host2:port2;param2=value2
 * 	...
 */
int extract_node_list(dmq_node_list_t* update_list, struct sip_msg* msg)
{
	int content_length, total_nodes = 0;
	str body;
	str tmp_uri;
	dmq_node_t *cur = NULL;
	dmq_node_t *ret, *find;
	char *tmp, *end, *match;

	if(!msg->content_length && (parse_headers(msg,HDR_CONTENTLENGTH_F,0)<0 || !msg->content_length)) {
		LM_ERR("no content length header found\n");
		return -1;
	}
	content_length = get_content_length(msg);
	if(!content_length) {
		LM_DBG("content length is 0\n");
		return total_nodes;
	}
	body.s = get_body(msg);
	body.len = content_length;
	tmp = body.s;
	end = body.s + body.len;
	
	/* acquire big list lock */
	lock_get(&update_list->lock);
	while(tmp < end) {
		match = q_memchr(tmp, '\n', end - tmp);
		if(match) {
			match++;
		} else {
			/* for the last line - take all of it */
			match = end;
		}
		/* create the orig_uri from the parsed uri line and trim it */
		tmp_uri.s = tmp;
		tmp_uri.len = match - tmp - 1;
		tmp = match;
		/* trim the \r, \n and \0's */
		trim_r(tmp_uri);
		find = build_dmq_node(&tmp_uri, 0);
		if(find==NULL)
			return -1;
		ret = find_dmq_node(update_list, find);
		if (!ret) {
			LM_DBG("found new node %.*s\n", STR_FMT(&tmp_uri));
			cur = build_dmq_node(&tmp_uri, 1);
			if(!cur) {
				LM_ERR("error creating new dmq node\n");
				goto error;
			}
			cur->next = update_list->nodes;
			update_list->nodes = cur;
			update_list->count++;
			total_nodes++;
		} else if (find->params && ret->status != find->status) {
			LM_DBG("updating status on %.*s from %d to %d\n",
				STR_FMT(&tmp_uri), ret->status, find->status);
			ret->status = find->status;
			total_nodes++;
		}
		destroy_dmq_node(find, 0);
	}

	/* release big list lock */
	lock_release(&update_list->lock);
	return total_nodes;
error:
	lock_release(&update_list->lock);
	return -1;
}
Esempio n. 4
0
int rls_handle_subscribe(struct sip_msg* msg, char* s1, char* s2)
{
	struct to_body *pto, *pfrom = NULL; 
	subs_t subs;
	pres_ev_t* event= NULL;
	str* contact= NULL;
	xmlDocPtr doc= NULL;
	xmlNodePtr service_node= NULL;
	unsigned int hash_code= 0;
	event_t* parsed_event;
	param_t* ev_param= NULL;
	int init_req;
	int reply_code;
	str reply_str;

	/*** filter: 'For me or for presence server?' */

	reply_code = 400;
	reply_str = pu_400_rpl;

	memset(&subs, 0, sizeof(subs_t));

	if ( parse_headers(msg,HDR_EOH_F, 0)==-1 )
	{
		LM_ERR("parsing headers\n");
		goto error;
	}

	/* check for Support: eventlist header */
	if(!msg->supported)
	{
		LM_DBG("no supported header found\n");
		return to_presence_code;
	}
	
	if(parse_supported(msg) < 0)
	{
		LM_ERR("failed to parse supported headers\n");
		reply_code = 500;
		reply_str = pu_500_rpl;
		goto error;
	}

	if(!(get_supported(msg) & F_SUPPORTED_EVENTLIST))
	{
		LM_DBG("No 'Support: eventlist' header found\n");
		return to_presence_code;
	}

	/* inspecting the Event header field */
	if(msg->event && msg->event->body.len > 0)
	{
		if (!msg->event->parsed && (parse_event(msg->event) < 0))
		{
			LM_ERR("cannot parse Event header\n");
			reply_code = 500;
			reply_str = pu_500_rpl;
			goto error;
		}
		if(! ( ((event_t*)msg->event->parsed)->parsed & rls_events) )
		{
			return to_presence_code;
		}
	}
	else
	{
		goto bad_event;
	}

	/* search event in the list */
	parsed_event= (event_t*)msg->event->parsed;
	event= pres_search_event(parsed_event);
	if(event== NULL)
	{
		goto bad_event;
	}
	subs.event= event;
	
	/* extract the id if any*/
	ev_param= parsed_event->params;
	while(ev_param)
	{
		if(ev_param->name.len== 2 && strncasecmp(ev_param->name.s, "id", 2)== 0)
		{
			subs.event_id= ev_param->body;
			break;
		}
		ev_param= ev_param->next;
	}

	pto = get_to(msg);
	if (pto == NULL || pto->error != PARSE_OK)
	{
		LM_ERR("parsing 'To' header failed\n");
		goto error;
	}

	if(parse_from_uri(msg)<0)
	{
		LM_ERR("failed to parse From header\n");
		goto error;
	}

	pfrom = (struct to_body*)msg->from->parsed;
	if(pfrom->tag_value.s ==NULL || pfrom->tag_value.len == 0)
	{
		LM_ERR("no from tag value present\n");
		goto error;
	}

	/* verify if the presentity URI is a resource list */
	if(pto->tag_value.s== NULL || pto->tag_value.len==0)
		/* if an initial Subscribe */
	{
		struct sip_uri fu = ((struct to_body*)msg->from->parsed)->parsed_uri;
		if( parse_sip_msg_uri(msg)< 0)
		{
			LM_ERR("parsing Request URI failed\n");
			goto error;
		}

		/*verify if Request URI represents a list by asking xcap server*/	
		if(uandd_to_uri(msg->parsed_uri.user, msg->parsed_uri.host,
					&subs.pres_uri)< 0)
		{
			LM_ERR("while constructing uri from user and domain\n");
			reply_code = 500;
			reply_str = pu_500_rpl;
			goto error;
		}
		
		if( get_resource_list(&subs.pres_uri, fu.user, fu.host,
					&service_node, &doc) < 0)
		{
			LM_ERR("failed to get resource list document\n");
			reply_code = 500;
			reply_str = pu_500_rpl;
			goto error;
		}
		
		if(doc== NULL|| service_node==NULL)
		{
			LM_DBG("list not found - search for uri = %.*s\n",subs.pres_uri.len,
				subs.pres_uri.s);
			pkg_free(subs.pres_uri.s);
			return to_presence_code;
		}
	}
	else  /* if request inside a dialog */
	{
		if( msg->callid==NULL || msg->callid->body.s==NULL)
		{
			LM_ERR("cannot parse callid header\n");
			goto error;
		}

		/* search if a stored dialog */
		hash_code= core_hash(&msg->callid->body, &pto->tag_value, hash_size);
		lock_get(&rls_table[hash_code].lock);

		if(pres_search_shtable(rls_table,msg->callid->body,
					pto->tag_value,	pfrom->tag_value, hash_code)== NULL)
		{
			lock_release(&rls_table[hash_code].lock);
			/* reply with Call/Transaction Does Not Exist */
			LM_DBG("No dialog match found\n");
			return to_presence_code;
		}
		lock_release(&rls_table[hash_code].lock);
	}

	/* extract dialog information from message headers */
	if(pres_extract_sdialog_info(&subs, msg, rls_max_expires, &init_req,
				server_address)< 0)
	{
		LM_ERR("bad Subscribe request\n");
		goto error;
	}

	reply_code = 500;
	reply_str = pu_500_rpl;


	if(init_req) /* if an initial subscribe */
	{
		/** reply with 200 OK*/
		if(reply_200(msg, &subs.local_contact, subs.expires, &subs.to_tag)< 0)
			goto error_free;
		hash_code= core_hash(&subs.callid, &subs.to_tag, hash_size);

		subs.local_cseq= 0;

		if(subs.expires!= 0)
		{
			subs.version= 1;
			if(pres_insert_shtable(rls_table, hash_code, &subs)< 0)
			{
				LM_ERR("while adding new subscription\n");
				goto error_free;
			}
		}
	}
	else
	{
		if(update_rlsubs(&subs, hash_code, &reply_code, &reply_str) < 0)
		{
			LM_ERR("while updating resource list subscription\n");
			goto error;
		}

		if(get_resource_list(&subs.pres_uri, subs.from_user,
					subs.from_domain, &service_node, &doc)< 0)
		{
			LM_ERR("when getting resource list\n");
			goto error;
		}
		if(doc== NULL || service_node== NULL)
		{
			LM_DBG("list not found( in-dialog request)- search for uri = %.*s\n",
					subs.pres_uri.len, subs.pres_uri.s);
			reply_code = 404;
			reply_str = pu_404_rpl;
			goto error;
		}

		/** reply with 200 OK*/
		if(reply_200(msg, &subs.local_contact, subs.expires, 0)< 0)
			goto error_free;
	}
/*** send Subscribe requests for all in the list */

	/* call sending Notify with full state */
	if(send_full_notify(&subs, service_node, subs.version,
				&subs.pres_uri,hash_code)< 0)
	{
		LM_ERR("while sending full state Notify\n");
		goto error_free;
	}

	if(resource_subscriptions(&subs, service_node)< 0)
	{
		LM_ERR("while sending Subscribe requests to resources in a list\n");
		goto error_free;
	}

	if(contact)
	{	
		if(contact->s)
			pkg_free(contact->s);
		pkg_free(contact);
	}
		
	pkg_free(subs.pres_uri.s);
	if(subs.record_route.s)
		pkg_free(subs.record_route.s);
	xmlFreeDoc(doc);
	return 1;


bad_event:
	if(reply_489(msg)< 0)
		LM_ERR("failed to send 489 reply\n");
	goto error_free;

error:
	if (rls_sigb.reply(msg, reply_code, &reply_str, 0) == -1)
	{
		LM_ERR("failed to send 400 reply\n");
		return -1;
	}


error_free:
	if(contact)
	{	
		if(contact->s)
			pkg_free(contact->s);
		pkg_free(contact);
	}
	if(subs.pres_uri.s)
		pkg_free(subs.pres_uri.s);
		
	if(subs.record_route.s)
			pkg_free(subs.record_route.s);	
	if(doc)
		xmlFreeDoc(doc);
	return -1;
}
Esempio n. 5
0
int Notify2Xmpp(struct sip_msg* msg, char* s1, char* s2)
{
	struct to_body *pto, *pfrom= NULL;
	str to_uri;
	str from_uri={0, 0};
	struct hdr_field* hdr= NULL;
	str body;
	xmlDocPtr doc= NULL;
	int is_terminated= 0;
	str id;
	ua_pres_t dialog;
	int event_flag= 0;
	char buf_to[256];

	memset(&dialog, 0, sizeof(ua_pres_t));

	LM_DBG("start...\n\n");

	if( parse_headers(msg,HDR_EOH_F, 0)==-1 )
	{
		LM_ERR("parsing headers\n");
		return -1;
	}
	if((!msg->event ) ||(msg->event->body.len<=0))
	{
		LM_ERR("Missing event header field value\n");
		return -1;
	}

	if( msg->to==NULL || msg->to->body.s==NULL)
	{
		LM_ERR("cannot parse TO header\n");
		return -1;
	}

	pto = get_to(msg);
	if (pto == NULL || pto->error != PARSE_OK) {
		LM_ERR("failed to parse TO header\n");
		return -1;
	}

	dialog.watcher_uri= &pto->uri;

	URI_ADD_NULL_TERM(to_uri, buf_to, dialog.watcher_uri);

	if (pto->tag_value.s==NULL || pto->tag_value.len==0 )
	{
		LM_ERR("to tag value not parsed\n");
		goto error;
	}
	id=  pto->tag_value;
	dialog.from_tag= id;

	if( msg->callid==NULL || msg->callid->body.s==NULL)
	{
		LM_ERR("cannot parse callid header\n");
		goto error;
	}
	dialog.call_id = msg->callid->body;

	if (!msg->from || !msg->from->body.s)
	{
		LM_ERR("ERROR cannot find 'from' header!\n");
		goto error;
	}
	if (msg->from->parsed == NULL)
	{
		/* parsing from header */
		if ( parse_from_header( msg )<0 )
		{
			LM_ERR("ERROR cannot parse From header\n");
			goto error;
		}
	}
	pfrom = (struct to_body*)msg->from->parsed;
	dialog.pres_uri= &pfrom->uri;

	from_uri.s = xmpp_uri_sip2xmpp(dialog.pres_uri);
	if(from_uri.s == 0)
	{
		LM_ERR("Failed to translate uri from sip to xmpp [%.*s]\n",
				dialog.pres_uri->len, dialog.pres_uri->s);
		goto error;
	}
	from_uri.len= strlen(from_uri.s);

	if( pfrom->tag_value.s ==NULL || pfrom->tag_value.len == 0)
	{
		LM_ERR("no from tag value present\n");
		goto error;
	}

	dialog.to_tag= pfrom->tag_value;
	dialog.flag|= XMPP_SUBSCRIBE;
	if(msg->event->body.len== 8 &&
			(strncasecmp(msg->event->body.s,"presence",8 )==0))
		event_flag|= PRESENCE_EVENT;
	else
	if(msg->event->body.len== 14 &&
			(strncasecmp(msg->event->body.s,"presence.winfo",14 )==0))
		event_flag|= PWINFO_EVENT;
	else
	{
		LM_ERR("wrong event\n");
		goto error;
	}
	dialog.event= event_flag;

	if(pua_is_dialog(&dialog)< 0) // verify if within a stored dialog
	{
		LM_ERR("Notify in a non existing dialog\n");
		goto error;
	}
	/*constructing the xml body*/
	if(get_content_length(msg) == 0 )
	{
		body.s= NULL;
		body.len= 0;
	}
	else
	{
		if ( get_body(msg,&body)!=0 || body.len==0)
		{
			LM_ERR("cannot extract body from msg\n");
			goto error;
		}
	}

	/* treat the two cases: event= presence & event=presence.winfo */
	if(event_flag & PRESENCE_EVENT)
	{
		LM_DBG("PRESENCE\n");
		hdr = get_header_by_static_name( msg, "Subscription-State" );
		if(hdr && strncasecmp(hdr->body.s,"terminated", 10)== 0)
		{
			/* chack if reason timeout => don't send notification */
			if(strncasecmp(hdr->body.s+11,"reason=timeout", 14)== 0)
			{
				LM_DBG("Received Notification with state"
					"terminated; reason= timeout=> don't send notification\n");
				return 1;
			}
			is_terminated= 1;

		}

		if(build_xmpp_content(&to_uri, &from_uri, &body, &id, is_terminated)< 0)
		{
			LM_ERR("in function build_xmpp_content\n");
			goto error;
		}
		xmlFreeDoc(doc);
	}
	else
	{
		if(event_flag & PWINFO_EVENT)
		{
			LM_DBG("PRESENCE.WINFO\n");
			hdr = get_header_by_static_name( msg, "Subscription-State" );
			if(hdr && strncasecmp(hdr->body.s,"terminated", 10)== 0)
			{
				LM_DBG("Notify for presence.winfo with"
					" Subscription-State terminated- should not translate\n");
				goto error;
			}
			if(winfo2xmpp(&to_uri, &body, &id)< 0)
			{
				LM_ERR("while sending subscription\n");
				goto error;
			}

		}
		else
		{
			LM_ERR("Missing or unsupported event header field value\n");
			goto error;
		}

	}
	return 1;

error:
	if(doc)
		xmlFreeDoc(doc);
	return 0;
}
Esempio n. 6
0
/*
 * Find credentials with given realm in a SIP message header
 */
inline int ims_find_credentials(struct sip_msg* _m, str* _realm,
		hdr_types_t _hftype, struct hdr_field** _h) {
	struct hdr_field** hook, *ptr, *prev;
	hdr_flags_t hdr_flags;
	int res;
	str* r;

	LM_DBG("Searching credentials in realm [%.*s]\n", _realm->len, _realm->s);

	/*
	 * Determine if we should use WWW-Authorization or
	 * Proxy-Authorization header fields, this parameter
	 * is set in www_authorize and proxy_authorize
	 */
	switch (_hftype) {
	case HDR_AUTHORIZATION_T:
		hook = &(_m->authorization);
		hdr_flags = HDR_AUTHORIZATION_F;
		break;
	case HDR_PROXYAUTH_T:
		hook = &(_m->proxy_auth);
		hdr_flags = HDR_PROXYAUTH_F;
		break;
	default:
		hook = &(_m->authorization);
		hdr_flags = HDR_T2F(_hftype);
		break;
	}

	/*
	 * If the credentials haven't been parsed yet, do it now
	 */
	if (*hook == 0) {
		/* No credentials parsed yet */
		LM_DBG("*hook == 0, No credentials parsed yet\n");
		if (parse_headers(_m, hdr_flags, 0) == -1) {
			LM_ERR("Error while parsing headers\n");
			return -1;
		}
	}

	ptr = *hook;
	LM_DBG("*hook = %p\n", ptr);
	/*
	 * Iterate through the credentials in the message and
	 * find credentials with given realm
	 */
	while (ptr) {
		res = parse_credentials(ptr);
		if (res < 0) {
			LM_ERR("Error while parsing credentials\n");
			return (res == -1) ? -2 : -3;
		} else if (res == 0) {
			LM_DBG("Credential parsed successfully\n");
			if (_realm->len) {
				r = &(((auth_body_t*) (ptr->parsed))->digest.realm);
				LM_DBG("Comparing realm <%.*s> and <%.*s>\n", _realm->len, _realm->s, r->len, r->s);
				if (r->len == _realm->len) {
					if (!strncasecmp(_realm->s, r->s, r->len)) {
						*_h = ptr;
						return 0;
					}
				}
			} else {
				*_h = ptr;
				return 0;
			}

		}

		prev = ptr;
		if (parse_headers(_m, hdr_flags, 1) == -1) {
			LM_ERR("Error while parsing headers\n");
			return -4;
		} else {
			if (prev != _m->last_header) {
				if (_m->last_header->type == _hftype)
					ptr = _m->last_header;
				else
					break;
			} else
				break;
		}
	}

	/*
	 * Credentials with given realm not found
	 */
	LM_DBG("Credentials with given realm not found\n");
	return 1;
}
Esempio n. 7
0
static void
__dialog_sendpublish(struct dlg_cell *dlg, int type, struct dlg_cb_params *_params)
{
	str tag = {0,0};
	struct to_body from;
	str peer_uri= {0, 0};
	char flag = DLG_PUB_AB;
	str flag_str;
	struct to_body peer_to_body;
	str entity_uri= {0, 0};
	int buf_len = 255;

	flag_str.s = &flag;
	flag_str.len = 1;

	memset(&from, 0, sizeof(struct to_body));
	memset(&peer_to_body, 0, sizeof(struct to_body));

	from.uri = dlg->from_uri;

	peer_uri.len = buf_len;
	peer_uri.s = (char*)pkg_malloc(buf_len);
	if(peer_uri.s == NULL)
	{
		LM_ERR("No more memory\n");
		goto error;
	}
	/* extract the peer_uri */
	if(dlg_api.fetch_dlg_value(dlg, &peer_dlg_var, &peer_uri, 1) < 0 || peer_uri.len==0)
	{
		LM_ERR("Failed to fetch peer uri dialog variable\n");
		goto error;
	}

	LM_DBG("peer_uri = %.*s\n", peer_uri.len, peer_uri.s);

	parse_to(peer_uri.s, peer_uri.s+peer_uri.len, &peer_to_body);
	if(peer_to_body.error != PARSE_OK)
	{
		LM_ERR("Failed to peer uri [%.*s]\n", peer_uri.len, peer_uri.s);
		goto error;
	}

	/* try to extract the flag */
	dlg_api.fetch_dlg_value(dlg, &flag_dlg_var, &flag_str, 1);
	LM_DBG("flag = %c\n", flag);

	entity_uri.len = buf_len;
	entity_uri.s = (char*)pkg_malloc(buf_len);
	if(entity_uri.s == NULL)
	{
		LM_ERR("No more memory\n");
		goto error;
	}
	/* check if entity is also custom */
	if(dlg_api.fetch_dlg_value(dlg, &entity_dlg_var, &entity_uri, 1) == 0)
	{
		/* overwrite from with this value */
		parse_to(entity_uri.s, entity_uri.s + entity_uri.len, &from);
		if(from.error != PARSE_OK)
		{
			LM_ERR("Wrong format for entity body\n");
			goto error;
		}
		LM_DBG("entity_uri = %.*s\n", entity_uri.len, entity_uri.s);
		LM_DBG("from uri = %.*s\n", from.uri.len, from.uri.s);
	}

	switch (type) {
	case DLGCB_FAILED:
	case DLGCB_TERMINATED:
	case DLGCB_EXPIRED:
		LM_DBG("dialog over, from=%.*s\n", dlg->from_uri.len, dlg->from_uri.s);
		if(flag == DLG_PUB_AB || flag == DLG_PUB_A)
			dialog_publish("terminated", &from, &peer_to_body, &(dlg->callid), 1, 0, 0, 0);
		if(flag == DLG_PUB_AB || flag == DLG_PUB_B)
			dialog_publish("terminated", &peer_to_body, &from, &(dlg->callid), 0, 0, 0, 0);
		break;
	case DLGCB_CONFIRMED:
	case DLGCB_REQ_WITHIN:
		LM_DBG("dialog confirmed, from=%.*s\n", dlg->from_uri.len, dlg->from_uri.s);
		if(flag == DLG_PUB_AB || flag == DLG_PUB_A)
			dialog_publish("confirmed", &from, &peer_to_body, &(dlg->callid), 1, dlg->lifetime, 0, 0);
		if(flag == DLG_PUB_AB || flag == DLG_PUB_B)
			dialog_publish("confirmed", &peer_to_body, &from, &(dlg->callid), 0, dlg->lifetime, 0, 0);
		break;
	case DLGCB_EARLY:
		LM_DBG("dialog is early, from=%.*s\n", from.uri.len, from.uri.s);
		if (include_tags) {
			/* get to tag*/
			if ( !_params->msg->to && ((parse_headers(_params->msg, HDR_TO_F,0)<0) || !_params->msg->to) ) {
				LM_ERR("bad reply or missing TO hdr :-/\n");
				tag.s = 0;
				tag.len = 0;
			} else {
				tag = get_to(_params->msg)->tag_value;
				if (tag.s==0 || tag.len==0) {
					LM_ERR("missing TAG param in TO hdr :-/\n");
					tag.s = 0;
					tag.len = 0;
				}
			}
			if(flag == DLG_PUB_AB || flag == DLG_PUB_A)
			{
				if (caller_confirmed) {
					dialog_publish("confirmed", &from, &peer_to_body, &(dlg->callid), 1,
						dlg->lifetime, &(dlg->legs[DLG_CALLER_LEG].tag), &tag);
				} else {
					dialog_publish("early", &from, &peer_to_body, &(dlg->callid), 1,
						dlg->lifetime, &(dlg->legs[DLG_CALLER_LEG].tag), &tag);
				}
			}

			if(flag == DLG_PUB_AB || flag == DLG_PUB_B)
			{
				dialog_publish("early", &peer_to_body, &from, &(dlg->callid), 0,
					dlg->lifetime, &tag, &(dlg->legs[DLG_CALLER_LEG].tag));
			}
		} else {
			if(flag == DLG_PUB_AB || flag == DLG_PUB_A)
			{
				if (caller_confirmed) {
					dialog_publish("confirmed", &from, &peer_to_body, &(dlg->callid), 1,
						dlg->lifetime, 0, 0);
				} else {
					dialog_publish("early", &from, &peer_to_body, &(dlg->callid), 1,
						dlg->lifetime, 0, 0);
				}
			}
			if(flag == DLG_PUB_AB || flag == DLG_PUB_B)
			{
				dialog_publish("early", &peer_to_body, &from, &(dlg->callid), 0,
					dlg->lifetime, 0, 0);
			}
		}
		break;
	default:
		LM_ERR("unhandled dialog callback type %d received, from=%.*s\n", type, dlg->from_uri.len, dlg->from_uri.s);
		if(flag == DLG_PUB_AB || flag == DLG_PUB_A)
			dialog_publish("terminated", &from, &peer_to_body, &(dlg->callid), 1, 0, 0, 0);
		if(flag == DLG_PUB_AB || flag == DLG_PUB_B)
			dialog_publish("terminated", &peer_to_body, &from, &(dlg->callid), 0, 0, 0, 0);
	}
error:
	if(peer_uri.s)
		pkg_free(peer_uri.s);
	if(entity_uri.s)
		pkg_free(entity_uri.s);
	if (peer_to_body.param_lst)
		free_to_params(&peer_to_body);
	if (from.param_lst)
		free_to_params(&from);
}
Esempio n. 8
0
	int
decode_contact_header (struct sip_msg *msg,char *unused1,char *unused2)
{

	contact_body_t *cb;
	contact_t *c;
	str uri;
	str newUri;
	char separator;
	int res;


#ifdef DEBUG
	str* ruri;
	fprintf (stdout,"---START--------DECODE CONTACT HEADER-----------------\n");
#endif

	if ((msg->contact == NULL)&&((parse_headers(msg,HDR_CONTACT_F,0) == -1) ||
				(msg->contact== NULL) ))
	{
		LM_ERR("no Contact header present\n");
		return -1;
	}

	separator = DEFAULT_SEPARATOR[0];
	if (contact_flds_separator != NULL)
		if (strlen(contact_flds_separator)>=1)
			separator = contact_flds_separator[0];

#ifdef DEBUG
	fprintf (stdout,"Using separator %c\n",separator);
	ruri = GET_RURI(msg);
	fprintf (stdout,"[len = %d]New uri is->%.*s\n",
			ruri->len,ruri->len,ruri->s);
	ruri = &msg->first_line.u.request.uri;
	fprintf (stdout, "INITIAL.s=[%.*s]\n", ruri->len, ruri->s);
#endif

	if (msg->contact->parsed == NULL) parse_contact (msg->contact);
	if (msg->contact->parsed != NULL)
	{
		cb = (contact_body_t *) msg->contact->parsed;
		c = cb->contacts;
		// we visit each contact
		if (c != NULL)
		{
			uri = c->uri;

			res = decode_uri (uri, separator, &newUri);
#ifdef DEBUG
			fprintf (stdout, "newuri.s=[%.*s]\n", newUri.len, newUri.s);
#endif
			if (res != 0)
			{
				LM_ERR("failed decoding contact.Code %d\n", res);
#ifdef STRICT_CHECK
				return res;
#endif
			}
			else
				if (patch (msg, uri.s, uri.len, newUri.s, newUri.len) < 0)
				{
					LM_ERR("lumping failed in mangling port \n");
					return -2;
				}

#ifdef DECODE_ALL_CONTACTS
			while (c->next != NULL)
			{
				c = c->next;
				uri = c->uri;

				res = decode_uri (uri, separator, &newUri);
				if (res != 0)
				{
					LM_ERR("failed decoding contact.Code %d\n",res);
#ifdef STRICT_CHECK
					return res;
#endif
				}
				else
					if (patch (msg, uri.s, uri.len, newUri.s, newUri.len) < 0)
					{
						LM_ERR("lumping failed in mangling port \n");
						return -3;
					}
			} // end while
#endif
		} // if c!= NULL
	} // end if
	else // after parsing still NULL
	{
		LM_ERR("unable to parse Contact header\n");
		return -4;
	}
#ifdef DEBUG
	fprintf (stdout,"---END--------DECODE CONTACT HEADER-----------------\n");fflush(stdout);
#endif
	return 1;
}
Esempio n. 9
0
//#define DEBUG
	int
encode_contact (struct sip_msg *msg, char *encoding_prefix,char *public_ip)
{

	contact_body_t *cb;
	contact_t *c;
	str uri;
	str newUri;
	int res;
	char separator;



	/*
	 * I have a list of contacts in contact->parsed which is of type contact_body_t
	 * inside i have a contact->parsed->contact which is the head of the list of contacts
	 * inside it is a
	 * str uri;
	 * struct contact *next;
	 * I just have to visit each uri and encode each uri according to a scheme
	 */

	if ((msg->contact == NULL)&&((parse_headers(msg,HDR_CONTACT_F,0) == -1) ||
				(msg->contact == NULL) ))
	{
		LM_ERR("no Contact header present\n");
		return -1;
	}


	separator = DEFAULT_SEPARATOR[0];
	if (contact_flds_separator != NULL)
		if (strlen(contact_flds_separator)>=1)
			separator = contact_flds_separator[0];

	if (msg->contact->parsed == NULL)	parse_contact (msg->contact);
	if (msg->contact->parsed != NULL)
	{
		cb = (contact_body_t *) msg->contact->parsed;
		c = cb->contacts;
		/* we visit each contact */
		if (c != NULL)
		{
			uri = c->uri;
			res = encode_uri (uri, encoding_prefix, public_ip,separator, &newUri);

			if (res != 0)
			{
				LM_ERR("failed encoding contact.Code %d\n", res);
#ifdef STRICT_CHECK
				return res;
#endif
			}
			else
				if (patch (msg, uri.s, uri.len, newUri.s, newUri.len) < 0)
				{
					LM_ERR("lumping failed in mangling port \n");
					return -2;
				}

			/* encoding next contacts too?*/
#ifdef ENCODE_ALL_CONTACTS
			while (c->next != NULL)
			{
				c = c->next;
				uri = c->uri;

				res = encode_uri (uri, encoding_prefix,public_ip,separator,&newUri);
				if (res != 0)
				{
					LM_ERR("failed encode_uri.Code %d\n",res);
#ifdef STRICT_CHECK
					return res;
#endif
				}
				else
					if (patch (msg, uri.s, uri.len, newUri.s, newUri.len)< 0)
					{
						LM_ERR("lumping failed in mangling port \n");
						return -3;
					}
			} /* while */
#endif /* ENCODE_ALL_CONTACTS */
		} /* if c != NULL */

	} /* end if */
	else /* after parsing still NULL */
	{
		LM_ERR("unable to parse Contact header\n");
		return -4;
	}
	return 1;
}
Esempio n. 10
0
int
sdp_mangle_ip (struct sip_msg *msg, char *oldip, char *newip)
{
	int i, oldContentLength, newContentLength, diff, oldlen,len,off,ret,needToDealocate;
	unsigned int mask, address, locatedIp;
	struct lump *l;
	regmatch_t pmatch;
	regex_t *re;
	char *s, *pos,*begin,*key;
	char buffer[16];	/* 123.456.789.123\0 */

#ifdef DEBUG
	fprintf (stdout,"---START--------MANGLE IP-----------------\n");
#endif

	
	key = IP_REGEX;

	/*
	 * Checking if msg has a payload
	 */
	if (msg == NULL)
		{
		LOG(L_ERR,"ERROR: sdp_mangle_ip: Received NULL for msg\n");
		return -1;
		}
	if ((msg->content_length==0) &&
				((parse_headers(msg,HDR_CONTENTLENGTH,0)==-1) ||
				 (msg->content_length==0) )){
			LOG(L_ERR,"ERROR: sdp_mangle_port: bad or missing "
					"Content-Length \n");
			return -2;
		}
        oldContentLength = get_content_length(msg);
        
	if (oldContentLength <= 0)
		{
		LOG(L_ERR,"ERROR: sdp_mangle_ip: Received <= for Content-Length\n");
		return -2;
		}

	/* checking oldip */
	if (oldip == NULL)
		{
		LOG(L_ERR,"ERROR: sdp_mangle_ip: Received NULL for oldip\n");
		return -3;
		}
	/* checking newip */
	if (newip == NULL)
		{
		LOG(L_ERR,"ERROR: sdp_mangle_ip: Received NULL for newip\n");
		return -4;
		}
	i = parse_ip_netmask (oldip, &pos, &mask);

	if (i == -1)
	{
		/* invalid value for the netmask specified in oldip */
		LOG(L_ERR,"ERROR: sdp_mangle_ip: invalid value for the netmask specified in oldip\n");
		return -5;
	}
	else
	{
		i = parse_ip_address (pos, &address);
		if (pos != NULL) free (pos);
		if (i == 0)
			{
			LOG(L_ERR,"ERROR: sdp_mangle_ip: invalid value for the ip specified in oldip\n");
			return -6;	/* parse error in ip */
			}
	}

	/* now we have in address/netmask binary values */

	begin = get_body(msg);//msg->buf + msg->first_line.len;	// inlocuiesc cu begin = getbody */
	ret = -1;
	len = strlen (newip);

	/* try to use precompiled expressions */
	needToDealocate = 0;
	if (ipExpression != NULL) 
		{
		re = ipExpression;
#ifdef DEBUG
		fprintf(stdout,"Using PRECOMPILED expression for ip ...\n");
#endif

		}
		else /* we are not using precompiled expressions */
			{
			re = pkg_malloc(sizeof(regex_t));
			if (re == NULL)
				{
				LOG(L_ERR,"ERROR: sdp_mangle_ip: Unable to allocate re\n");
				return -7;
				}
			needToDealocate = 1;
			if ((regcomp (re, key, REG_EXTENDED)) != 0)
				{
				LOG(L_ERR,"ERROR: sdp_mangle_ip: Unable to compile %s \n",key);
				return -8;
				}
#ifdef DEBUG
		fprintf(stdout,"Using ALLOCATED expression for ip ...\n");
#endif
			}

	diff = 0;
	while ((begin < msg->buf + msg->len) && (regexec (re, begin, 1, &pmatch, 0) == 0))
	{
		off = begin - msg->buf;
		if (pmatch.rm_so == -1)
		{
			LOG (L_ERR,"ERROR: sdp_mangler_ip: offset unknown\n");
			return -9;
		}
	
#ifdef STRICT_CHECK
		pmatch.rm_eo --; /* return with one space,\n,\r */
#endif
	
		/* 
                for BSD and Solaris we avoid memrchr
                pos = (char *) memrchr (begin + pmatch.rm_so, ' ',pmatch.rm_eo - pmatch.rm_so); 
                */
                pos = begin+pmatch.rm_eo;
                do pos--; while (*pos != ' '); /* we should find ' ' because we matched c=IN IP4 ip */

		pos++;		/* jumping over space */
		oldlen = (pmatch.rm_eo - pmatch.rm_so) - (pos - (begin + pmatch.rm_so));	/* ip length */
		if (oldlen > 15)
		{
			LOG(L_WARN,"WARNING: sdp_mangle_ip: Silent fail because oldlen > 15\n");
#ifdef STRICT_CHECK
			return -10;
#else 
			goto continue2;	/* silent fail return -10; invalid ip format ,probably like 1000.3.12341.2 */
#endif

			
		}
		buffer[0] = '\0';
		strncat ((char *) buffer, pos, oldlen);	
		buffer[oldlen] = '\0';
		i = parse_ip_address (buffer, &locatedIp);
		if (i == 0)
		{
			LOG(L_WARN,"WARNING: sdp_mangle_ip: Silent fail on parsing matched address \n");
			
#ifdef STRICT_CHECK
			return -11;
#else 
			goto continue2;	
#endif
		}
		if (same_net (locatedIp, address, mask) == 0)
		{
			LOG(L_WARN,"WARNING: sdp_mangle_ip: Silent fail because matched address is not in network\n");
#ifdef DEBUG
		fprintf(stdout,"Extracted ip is %s and not mangling \n",buffer);
#endif
			goto continue2;	/* not in the same net, skiping */
		}
#ifdef DEBUG
		fprintf(stdout,"Extracted ip is %s and mangling to %s\n",buffer,newip);
#endif


		/* replacing ip */

		/* deleting old ip */
		if ((l = del_lump (msg,pmatch.rm_so + off + (pos - (begin + pmatch.rm_so)),oldlen, 0)) == 0)
		{
			LOG (L_ERR,"ERROR: sdp_mangle_ip: del_lump failed\n");
			return -12;
		}
		s = pkg_malloc (len);
		if (s == 0)
		{
			LOG (L_ERR,"ERROR: sdp_mangle_ip: mem. allocation failure\n");
			return -13;
		}
		memcpy (s, newip, len);

		if (insert_new_lump_after (l, s, len, 0) == 0)
		{
			LOG (L_ERR, "ERROR: sdp_mangle_ip: could not insert new lump\n");
			pkg_free (s);
			return -14;
		}
		diff = diff + len /*new length */  - oldlen;
		/* new cycle */
		ret++;
continue2:
		begin = begin + pmatch.rm_eo;

	}			/* while */
	if (needToDealocate)
	{
	regfree (re);		/* if I am going to use precompiled expressions to be removed */
	pkg_free(re);
#ifdef DEBUG
		fprintf(stdout,"Dealocating expression for ip ...\n");
#endif
	}
	
	if (diff != 0)
	{
		newContentLength = oldContentLength + diff;
		patch_content_length (msg, newContentLength);
	}

#ifdef DEBUG
	fprintf (stdout,"---END--------MANGLE IP-----------------\n");
#endif

	return ret+2;

}
Esempio n. 11
0
int
sdp_mangle_port (struct sip_msg *msg, char *offset, char *unused)
{
	int oldContentLength, newContentLength, oldlen, err, oldPort, newPort,
		diff, offsetValue,len,off,ret,needToDealocate;
	struct lump *l;
	regmatch_t pmatch;
	regex_t *re;
	char *s, *pos,*begin,*key;
	char buf[6];
	
	
	
	key = PORT_REGEX;
	/*
	 * Checking if msg has a payload
	 */
	if (msg == NULL)
		{
		LOG(L_ERR,"ERROR: sdp_mangle_port: Received NULL for msg \n");
		return -1;
		}
                
	if ((msg->content_length==0) &&
			((parse_headers(msg,HDR_CONTENTLENGTH,0)==-1) ||
			 (msg->content_length==0) )){
		LOG(L_ERR,"ERROR: sdp_mangle_port: bad or missing "
				"Content-Length \n");
		return -2;
	}

        oldContentLength = get_content_length(msg);
        
	if (oldContentLength <= 0)
		{
		LOG(L_ERR,"ERROR: sdp_mangle_port: Received <= 0 for Content-Length \n");
		return -2;
		}
	
	if (offset == NULL)
		return -14;
	if (sscanf (offset, "%d", &offsetValue) != 1)
	{
		LOG(L_ERR,"ERROR: sdp_mangle_port: Invalid value for offset \n");
		return -13;
	}
	
	//offsetValue = (int)offset;
#ifdef DEBUG
	fprintf (stdout,"---START--------MANGLE PORT-----------------\n");
	fprintf(stdout,"===============OFFSET = %d\n",offsetValue);
#endif
	
	if ((offsetValue < MIN_OFFSET_VALUE) || (offsetValue > MAX_OFFSET_VALUE))
	{
		LOG(L_ERR,"ERROR: sdp_mangle_port: Invalid value %d for offset \n",offsetValue);
		return -3;
	}
	begin = get_body(msg); //msg->buf + msg->first_line.len;	// inlocuiesc cu begin = getbody */
	ret = -1;

	/* try to use precompiled expressions */
	needToDealocate = 0;
	if (portExpression != NULL) 
		{
		re = portExpression;
#ifdef DEBUG
		fprintf(stdout,"Using PRECOMPILED expression for port ...\n");
#endif
		}
		else /* we are not using precompiled expressions */
			{
			re = pkg_malloc(sizeof(regex_t));
			if (re == NULL)
				{
				LOG(L_ERR,"ERROR: sdp_mangle_port: Unable to allocate re\n");
				return -4;
				}
			needToDealocate = 1;
			if ((regcomp (re, key, REG_EXTENDED)) != 0)
				{
				LOG(L_ERR,"ERROR: sdp_mangle_port: Unable to compile %s \n",key);
				return -5;
				}
#ifdef DEBUG
		fprintf(stdout,"Using ALLOCATED expression for port ...\n");
#endif

			}
	
	diff = 0;
	while ((begin < msg->buf + msg->len) && (regexec (re, begin, 1, &pmatch, 0) == 0))
	{
		off = begin - msg->buf;
		if (pmatch.rm_so == -1)
		{
			LOG (L_ERR, "ERROR: sdp_mangle_port: offset unknown\n");
			return -6;
		}
	
#ifdef STRICT_CHECK
		pmatch.rm_eo --; /* return with one space */
#endif
	
		/* 
                for BSD and Solaris we avoid memrchr
                pos = (char *) memrchr (begin + pmatch.rm_so, ' ',pmatch.rm_eo - pmatch.rm_so); 
                */
                pos = begin+pmatch.rm_eo;
#ifdef DEBUG
                printf("begin=%c pos=%c rm_so=%d rm_eo=%d\n",*begin,*pos,pmatch.rm_so,pmatch.rm_eo);
#endif
                do pos--; while (*pos != ' '); /* we should find ' ' because we matched m=audio port */
                
		pos++;		/* jumping over space */
		oldlen = (pmatch.rm_eo - pmatch.rm_so) - (pos - (begin + pmatch.rm_so));	/* port length */

		/* convert port to int */
		oldPort = str2s (pos, oldlen, &err);
#ifdef DEBUG
                printf("port to convert [%.*s] to int\n",oldlen,pos);
#endif
		if (err)
			{
			LOG(L_ERR,"ERROR: sdp_mangle_port: Error converting [%.*s] to int\n",oldlen,pos);
#ifdef STRICT_CHECK
			return -7;
#else
			goto continue1;
#endif
			}
		if ((oldPort < MIN_ORIGINAL_PORT) || (oldPort > MAX_ORIGINAL_PORT))	/* we silently fail,we ignore this match or return -11 */
		{
#ifdef DEBUG
                printf("WARNING: sdp_mangle_port: Silent fail for not matching old port %d\n",oldPort);
#endif

			LOG(L_WARN,"WARNING: sdp_mangle_port: Silent fail for not matching old port %d\n",oldPort);
#ifdef STRICT_CHECK
			return -8;
#else
			goto continue1;
#endif
		}
                if ((offset[0] != '+')&&(offset[0] != '-')) newPort = offsetValue;//fix value
		else newPort = oldPort + offsetValue;
		/* new port is between 1 and 65536, or so should be */
		if ((newPort < MIN_MANGLED_PORT) || (newPort > MAX_MANGLED_PORT))	/* we silently fail,we ignore this match */
		{
#ifdef DEBUG
                printf("WARNING: sdp_mangle_port: Silent fail for not matching new port %d\n",newPort);
#endif
                
			LOG(L_WARN,"WARNING: sdp_mangle_port: Silent fail for not matching new port %d\n",newPort);
#ifdef STRICT_CHECK
			return -9;
#else
			goto continue1;
#endif
		}

#ifdef DEBUG
		fprintf(stdout,"Extracted port is %d and mangling to %d\n",oldPort,newPort);
#endif

		/*
		len = 1;
		while ((newPort = (newPort / 10)) != 0)	len++;
		newPort = oldPort + offsetValue;
		*/
		if (newPort >= 10000) len = 5;
			else
				if (newPort >= 1000) len = 4;
					else
						if (newPort >= 100) len = 3;
							else
								if (newPort >= 10) len = 2;
									else len = 1;

		/* replaced five div's + 1 add with most probably 1 comparison or 2 */							
		
		/* deleting old port */
		if ((l = del_lump (msg,pmatch.rm_so + off + (pos -(begin + pmatch.rm_so)),oldlen, 0)) == 0)
		{
			LOG (L_ERR,"ERROR: sdp_mangle_port: del_lump failed\n");
			return -10;
		}
		s = pkg_malloc (len);
		if (s == 0)
		{
			LOG (L_ERR,"ERROR: sdp_mangle_port : memory allocation failure\n");
			return -11;
		}
		snprintf (buf, len + 1, "%u", newPort);	/* converting to string */
		memcpy (s, buf, len);

		if (insert_new_lump_after (l, s, len, 0) == 0)
		{
			LOG (L_ERR, "ERROR: sdp_mangle_port: could not insert new lump\n");
			pkg_free (s);
			return -12;
		}
		diff = diff + len /*new length */  - oldlen;
		/* new cycle */
		ret++;
#ifndef STRICT_CHECK
continue1:
#endif
		begin = begin + pmatch.rm_eo;

	}			/* while  */
	if (needToDealocate)
		{
		regfree (re);
		pkg_free(re);
#ifdef DEBUG
		fprintf(stdout,"Dealocating expression for port ...\n");
#endif
		}
	
	if (diff != 0)
	{
		newContentLength = oldContentLength + diff;
		patch_content_length (msg, newContentLength);
	}

#ifdef DEBUG
	fprintf (stdout,"---END--------MANGLE PORT-----------------\n");
#endif

	return ret+2;
}
Esempio n. 12
0
/**
 * manage SIP message
 */
int xjab_manage_sipmsg(struct sip_msg *msg, int type)
{
	str body, dst, from_uri;
	xj_sipmsg jsmsg;
	int pipe, fl;
	t_xj_jkey jkey, *p;
	int mime;

	body.s=0;  /* fixes gcc 4.0 warning */
	body.len=0;
	// extract message body - after that whole SIP MESSAGE is parsed
	if (type==XJ_SEND_MESSAGE)
	{
		/* get the message's body */
		body.s = get_body( msg );
		if(body.s==0)
		{
			LOG(L_ERR,"XJAB:xjab_manage_sipmsg: ERROR cannot extract body from"
				" msg\n");
			goto error;
		}

		/* content-length (if present) must be already parsed */
		if(!msg->content_length)
		{
			LOG(L_ERR,"XJAB:xjab_manage_sipmsg: ERROR no Content-Length"
					" header found!\n");
			goto error;
		}
		body.len = get_content_length(msg);

		/* parse the content-type header */
		if((mime=parse_content_type_hdr(msg))<1)
		{
			LOG(L_ERR,"XJAB:xjab_manage_sipmsg: ERROR cannot parse"
					" Content-Type header\n");
			goto error;
		}

		/* check the content-type value */
		if(mime!=(TYPE_TEXT<<16)+SUBTYPE_PLAIN
			&& mime!=(TYPE_MESSAGE<<16)+SUBTYPE_CPIM)
		{
			LOG(L_ERR,"XJAB:xjab_manage_sipmsg: ERROR invalid content-type for"
				" a message request! type found=%d\n", mime);
			goto error;
		}
	}

	// check for TO and FROM headers - if is not SIP MESSAGE
	if(parse_headers( msg, HDR_TO_F|HDR_FROM_F, 0)==-1 || !msg->to
			|| !msg->from)
	{
		LOG(L_ERR,"XJAB:xjab_manage_sipmsg: cannot find TO or FROM HEADERS!\n");
		goto error;
	}

	/* parsing from header */
	if ( parse_from_header( msg )==-1 || msg->from->parsed==NULL)
	{
		DBG("ERROR:xjab_manage_sipmsg: cannot get FROM header\n");
		goto error;
	}
	from_uri.s = ((struct to_body*)msg->from->parsed)->uri.s;
	from_uri.len = ((struct to_body*)msg->from->parsed)->uri.len;
	if(xj_extract_aor(&from_uri, 0))
	{
		DBG("ERROR:xjab_manage_sipmsg: cannot get AoR from FROM header\n");
		goto error;
	}

	jkey.hash = xj_get_hash(&from_uri, NULL);
	jkey.id = &from_uri;
	// get the communication pipe with the worker
	switch(type)
	{
		case XJ_SEND_MESSAGE:
		case XJ_JOIN_JCONF:
		case XJ_GO_ONLINE:
			if((pipe = xj_wlist_get(jwl, &jkey, &p)) < 0)
			{
				DBG("XJAB:xjab_manage_sipmsg: cannot find pipe of the worker!\n");
				goto error;
			}
		break;
		case XJ_EXIT_JCONF:
		case XJ_GO_OFFLINE:
			if((pipe = xj_wlist_check(jwl, &jkey, &p)) < 0)
			{
				DBG("XJAB:xjab_manage_sipmsg: no open Jabber session for"
						" <%.*s>!\n", from_uri.len, from_uri.s);
				goto error;
			}
		break;
		default:
			DBG("XJAB:xjab_manage_sipmsg: ERROR:strange SIP msg type!\n");
			goto error;
	}

	// if is for going ONLINE/OFFLINE we do not need the destination
	if(type==XJ_GO_ONLINE || type==XJ_GO_OFFLINE)
		goto prepare_job;

	// determination of destination
	// - try to get it from new_uri, r-uri or to hdr, but check it against
	// jdomain and aliases
	dst.len = 0;
	if( msg->new_uri.len > 0)
	{
		dst.s = msg->new_uri.s;
		dst.len = msg->new_uri.len;
		if(xj_wlist_check_aliases(jwl, &dst))
			dst.len = 0;
#ifdef XJ_EXTRA_DEBUG
		else
			DBG("XJAB:xjab_manage_sipmsg: using NEW URI for destination\n");
#endif
	}

	if (dst.len == 0 &&  msg->first_line.u.request.uri.s != NULL
			&& msg->first_line.u.request.uri.len > 0 )
	{
		dst.s = msg->first_line.u.request.uri.s;
		dst.len = msg->first_line.u.request.uri.len;
		if(xj_wlist_check_aliases(jwl, &dst))
			dst.len = 0;
#ifdef XJ_EXTRA_DEBUG
		else
			DBG("XJAB:xjab_manage_sipmsg: using R-URI for destination\n");
#endif
	}

	if(dst.len == 0 && msg->to->parsed)
	{
		dst.s = ((struct to_body*)msg->to->parsed)->uri.s;
		dst.len = ((struct to_body*)msg->to->parsed)->uri.len;
		if(dst.s == NULL || xj_wlist_check_aliases(jwl, &dst))
			dst.len = 0;
#ifdef XJ_EXTRA_DEBUG
		else
			DBG("XJAB:xjab_manage_sipmsg: using TO-URI for destination\n");
#endif
	}

	if(dst.len == 0)
	{
		DBG("XJAB:xjab_manage_sipmsg: destination not found in SIP message\n");
		goto error;
	}

	/** skip 'sip:' and parameters in destination address */
	if(xj_extract_aor(&dst, 1))
	{
		DBG("ERROR:xjab_manage_sipmsg: cannot get AoR for destination\n");
		goto error;
	}
#ifdef XJ_EXTRA_DEBUG
	DBG("XJAB:xjab_manage_sipmsg: DESTINATION after correction [%.*s].\n",
				dst.len, dst.s);
#endif

prepare_job:
	//putting the SIP message parts in share memory to be accessible by workers
    jsmsg = (xj_sipmsg)shm_malloc(sizeof(t_xj_sipmsg));
	memset(jsmsg, 0, sizeof(t_xj_sipmsg));
    if(jsmsg == NULL)
    	return -1;

	switch(type)
	{
		case XJ_SEND_MESSAGE:
			jsmsg->msg.len = body.len;
			if((jsmsg->msg.s = (char*)shm_malloc(jsmsg->msg.len+1)) == NULL)
			{
				shm_free(jsmsg);
				goto error;
			}
			strncpy(jsmsg->msg.s, body.s, jsmsg->msg.len);
		break;
		case XJ_GO_ONLINE:
		case XJ_GO_OFFLINE:
			dst.len = 0;
			dst.s = 0;
		case XJ_JOIN_JCONF:
		case XJ_EXIT_JCONF:
			jsmsg->msg.len = 0;
			jsmsg->msg.s = NULL;
		break;
		default:
			DBG("XJAB:xjab_manage_sipmsg: this SHOULD NOT appear\n");
			shm_free(jsmsg);
			goto error;
	}
	if(dst.len>0)
	{
		jsmsg->to.len = dst.len;
		if((jsmsg->to.s = (char*)shm_malloc(jsmsg->to.len+1))==NULL)
		{
			if(type == XJ_SEND_MESSAGE)
				shm_free(jsmsg->msg.s);
			shm_free(jsmsg);
			goto error;
		}
		strncpy(jsmsg->to.s, dst.s, jsmsg->to.len);
	}
	else
	{
		jsmsg->to.len = 0;
		jsmsg->to.s   = 0;
	}

	jsmsg->jkey = p;
	jsmsg->type = type;
	//jsmsg->jkey->hash = jkey.hash;

	DBG("XJAB:xjab_manage_sipmsg:%d: sending <%p> to worker through <%d>\n",
			getpid(), jsmsg, pipe);
	// sending the SHM pointer of SIP message to the worker
	fl = write(pipe, &jsmsg, sizeof(jsmsg));
	if(fl != sizeof(jsmsg))
	{
		DBG("XJAB:xjab_manage_sipmsg: error when writing to worker pipe!\n");
		if(type == XJ_SEND_MESSAGE)
			shm_free(jsmsg->msg.s);
		shm_free(jsmsg->to.s);
		shm_free(jsmsg);
		goto error;
	}

	return 1;
error:
	return -1;
}
Esempio n. 13
0
/* returns 0 if ok, -1 for errors */
int parse_msg(char* buf, unsigned int len, struct sip_msg* msg)
{

	char *tmp;
	char* rest;
	struct msg_start *fl;
	int offset;
	hdr_flags_t flags;

	/* eat crlf from the beginning */
	for (tmp=buf; (*tmp=='\n' || *tmp=='\r')&&
			(unsigned int)(tmp-buf) < len ; tmp++);
	offset=tmp-buf;
	fl=&(msg->first_line);
	rest=parse_first_line(tmp, len-offset, fl);

	offset+=rest-tmp;
	tmp=rest;
	switch(fl->type){
		case SIP_INVALID:
			LM_DBG("invalid message\n");
			/* if failed to parse the first line, we simply consider that the whole
			   buffer was parsed, so that nothing is left to be parsed :) - this will
			   do the trick and make "msg" struct acceptable for following parsing
			   attempts */
			msg->unparsed = msg->buf + msg->len;
			goto error;
			break;
		case SIP_REQUEST:
			LM_DBG("SIP Request:\n");
			LM_DBG(" method:  <%.*s>\n",fl->u.request.method.len,
				ZSW(fl->u.request.method.s));
			LM_DBG(" uri:     <%.*s>\n",fl->u.request.uri.len,
				ZSW(fl->u.request.uri.s));
			LM_DBG(" version: <%.*s>\n",fl->u.request.version.len,
				ZSW(fl->u.request.version.s));
			flags=HDR_VIA_F;
			break;
		case SIP_REPLY:
			LM_DBG("SIP Reply  (status):\n");
			LM_DBG(" version: <%.*s>\n",fl->u.reply.version.len,
					ZSW(fl->u.reply.version.s));
			LM_DBG(" status:  <%.*s>\n", fl->u.reply.status.len,
					ZSW(fl->u.reply.status.s));
			LM_DBG(" reason:  <%.*s>\n", fl->u.reply.reason.len,
					ZSW(fl->u.reply.reason.s));
			flags=HDR_VIA_F;
			break;
		default:
			LM_DBG("unknown type %d\n",fl->type);
			goto error;
	}
	msg->unparsed=tmp;
	/*find first Via: */
	if (parse_headers(msg, flags, 0)==-1) goto error;

#ifdef EXTRA_DEBUG
	/* dump parsed data */
	if (msg->via1){
		LM_DBG(" first  via: <%.*s/%.*s/%.*s> <%.*s:%.*s(%d)>",
			msg->via1->name.len,
			ZSW(msg->via1->name.s),
			msg->via1->version.len,
			ZSW(msg->via1->version.s),
			msg->via1->transport.len,
			ZSW(msg->via1->transport.s),
			msg->via1->host.len,
			ZSW(msg->via1->host.s),
			msg->via1->port_str.len,
			ZSW(msg->via1->port_str.s),
			msg->via1->port);
		if (msg->via1->params.s)  LM_DBG(";<%.*s>",
				msg->via1->params.len, ZSW(msg->via1->params.s));
		if (msg->via1->comment.s)
				LM_DBG(" <%.*s>",
					msg->via1->comment.len, ZSW(msg->via1->comment.s));
		LM_DBG ("\n");
	}
	if (msg->via2){
		LM_DBG(" first  via: <%.*s/%.*s/%.*s> <%.*s:%.*s(%d)>",
			msg->via2->name.len,
			ZSW(msg->via2->name.s),
			msg->via2->version.len,
			ZSW(msg->via2->version.s),
			msg->via2->transport.len,
			ZSW(msg->via2->transport.s),
			msg->via2->host.len,
			ZSW(msg->via2->host.s),
			msg->via2->port_str.len,
			ZSW(msg->via2->port_str.s),
			msg->via2->port);
		if (msg->via2->params.s)  LM_DBG(";<%.*s>",
				msg->via2->params.len, ZSW(msg->via2->params.s));
		if (msg->via2->comment.s) LM_DBG(" <%.*s>",
				msg->via2->comment.len, ZSW(msg->via2->comment.s));
		LM_DBG ("\n");
	}
#endif


#ifdef EXTRA_DEBUG
	LM_DBG("exiting\n");
#endif

	return 0;

error:
	/* more debugging, msg->orig is/should be null terminated*/
	LM_ERR("message=<%.*s>\n", (int)len, ZSW(buf));
	return -1;
}
Esempio n. 14
0
/* removes first via & sends msg to the second
 * - mode param controls if modules sip response callbacks are executed */
static int do_forward_reply(struct sip_msg* msg, int mode)
{
	char* new_buf;
	struct dest_info dst;
	unsigned int new_len;
	int r;
#ifdef USE_TCP
	char* s;
	int len;
#endif
	init_dest_info(&dst);
	new_buf=0;
	/*check if first via host = us */
	if (check_via){
		if (check_self(&msg->via1->host,
					msg->via1->port?msg->via1->port:SIP_PORT,
					msg->via1->proto)!=1){
			LOG(L_NOTICE, "ERROR: forward_reply: host in first via!=me :"
					" %.*s:%d\n", msg->via1->host.len, msg->via1->host.s,
									msg->via1->port);
			/* send error msg back? */
			goto error;
		}
	}
	
	/* check modules response_f functions */
	if(likely(mode==0)) {
		for (r=0; r<mod_response_cbk_no; r++)
			if (mod_response_cbks[r](msg)==0) goto skip;
	}
	/* we have to forward the reply stateless, so we need second via -bogdan*/
	if (parse_headers( msg, HDR_VIA2_F, 0 )==-1 
		|| (msg->via2==0) || (msg->via2->error!=PARSE_OK))
	{
		/* no second via => error */
		LOG(L_DBG, "reply cannot be forwarded - no 2nd via\n");
		goto error;
	}

	new_buf = build_res_buf_from_sip_res( msg, &new_len);
	if (!new_buf){
		LOG(L_ERR, "ERROR: forward_reply: building failed\n");
		goto error;
	}

	dst.proto=msg->via2->proto;
	SND_FLAGS_OR(&dst.send_flags, &msg->fwd_send_flags, &msg->rpl_send_flags);
	if (update_sock_struct_from_via( &dst.to, msg, msg->via2 )==-1) goto error;
#ifdef USE_COMP
	dst.comp=msg->via2->comp_no;
#endif

#if defined USE_TCP || defined USE_SCTP
	if (
#ifdef USE_TCP
			dst.proto==PROTO_TCP
			|| dst.proto==PROTO_WS
#ifdef USE_TLS
			|| dst.proto==PROTO_TLS
			|| dst.proto==PROTO_WSS
#endif
#ifdef USE_SCTP
			||
#endif /* USE_SCTP */
#endif /* USE_TCP */
#ifdef USE_SCTP
			dst.proto==PROTO_SCTP
#endif /* USE_SCTP */
			){
		/* find id in i param if it exists */
		if (msg->via1->i && msg->via1->i->value.s){
			s=msg->via1->i->value.s;
			len=msg->via1->i->value.len;
			DBG("forward_reply: i=%.*s\n",len, ZSW(s));
			if (reverse_hex2int(s, len, (unsigned int*)&dst.id)<0){
				LOG(L_ERR, "ERROR: forward_reply: bad via i param \"%.*s\"\n",
						len, ZSW(s));
					dst.id=0;
			}
		}		
				
	} 
#endif

	apply_force_send_socket(&dst, msg);

	if (msg_send(&dst, new_buf, new_len)<0)
	{
		STATS_RPL_FWD_DROP();
		goto error;
	}
	/* call onsend_route */
	if(dst.send_sock == NULL) {
		dst.send_sock=get_send_socket(msg, &dst.to, dst.proto);
		if (dst.send_sock==0){
			LOG(L_ERR, "forward_reply: ERROR: cannot forward reply\n");
			goto done;
		}
	}
	run_onsend(msg, &dst, new_buf, new_len);

	done:
#ifdef STATS
	STATS_TX_RESPONSE(  (msg->first_line.u.reply.statuscode/100) );
#endif

	DBG(" reply forwarded to %.*s:%d\n", 
			msg->via2->host.len, msg->via2->host.s,
			(unsigned short) msg->via2->port);

	STATS_RPL_FWD_OK();
	pkg_free(new_buf);
skip:
	return 0;
error:
	if (new_buf) pkg_free(new_buf);
	return -1;
}
Esempio n. 15
0
/*! \brief removes first via & sends msg to the second */
int forward_reply(struct sip_msg* msg)
{
	char* new_buf;
	union sockaddr_union* to;
	unsigned int new_len;
	struct sr_module *mod;
	int proto;
	int id; /* used only by tcp*/
	struct socket_info *send_sock;
#ifdef USE_TCP
	char* s;
	int len;
#endif
	
	to=0;
	id=0;
	new_buf=0;
	/*check if first via host = us */
	if (check_via){
		if (check_self(&msg->via1->host,
					msg->via1->port?msg->via1->port:SIP_PORT,
					msg->via1->proto)!=1){
			LM_ERR("host in first via!=me : %.*s:%d\n", 
				msg->via1->host.len, msg->via1->host.s,	msg->via1->port);
			/* send error msg back? */
			goto error;
		}
	}
	/* quick hack, slower for multiple modules*/
	for (mod=modules;mod;mod=mod->next){
		if ((mod->exports) && (mod->exports->response_f)){
			LM_DBG("found module %s, passing reply to it\n",
					mod->exports->name);
			if (mod->exports->response_f(msg)==0) goto skip;
		}
	}

	/* if stateless fwd was disabled, we cannot have stateless replies here*/
	if (sl_fwd_disabled)
		goto skip;

	/* we have to forward the reply stateless, so we need second via -bogdan*/
	if (parse_headers( msg, HDR_VIA2_F, 0 )==-1 
		|| (msg->via2==0) || (msg->via2->error!=PARSE_OK))
	{
		/* no second via => error */
		LM_ERR("no 2nd via found in reply from %s:%d <%.*s>\n",
			ip_addr2a(&msg->rcv.src_ip),msg->rcv.src_port, msg->len,msg->buf );
		goto error;
	}

	to=(union sockaddr_union*)pkg_malloc(sizeof(union sockaddr_union));
	if (to==0){
		LM_ERR("out of pkg memory\n");
		goto error;
	}

	proto=msg->via2->proto;
	if (update_sock_struct_from_via( to, msg, msg->via2 )==-1) goto error;

#ifdef USE_TCP
	if (proto==PROTO_TCP
#ifdef USE_TLS
			|| proto==PROTO_TLS
#endif
			){
		/* find id in i param if it exists */
		if (msg->via1->i&&msg->via1->i->value.s){
			s=msg->via1->i->value.s;
			len=msg->via1->i->value.len;
			id=reverse_hex2int(s, len);
		}
	}
#endif

	send_sock = get_send_socket(msg, to, proto);

	new_buf = build_res_buf_from_sip_res( msg, &new_len, send_sock);
	if (!new_buf){
		LM_ERR("failed to build rpl from req failed\n");
		goto error;
	}

	if (msg_send(send_sock, proto, to, id, new_buf, new_len)<0) {
		update_stat( drp_rpls, 1);
		goto error0;
	}
	update_stat( fwd_rpls, 1);
	/*
	 * If no port is specified in the second via, then this
	 * message output a wrong port number - zero. Despite that
	 * the correct port is choosen in update_sock_struct_from_via,
	 * as its visible with su_getport(to); .
	 */
	LM_DBG("reply forwarded to %.*s:%d\n", msg->via2->host.len, 
		msg->via2->host.s, (unsigned short) msg->via2->port);

	pkg_free(new_buf);
	pkg_free(to);
skip:
	return 0;
error:
	update_stat( err_rpls, 1);
error0:
	if (new_buf) pkg_free(new_buf);
	if (to) pkg_free(to);
	return -1;
}
Esempio n. 16
0
int select_anyheader(str* res, select_t* s, struct sip_msg* msg)
{
	struct hdr_field *hf, *hf0;
	int hi;
	char c;
	struct hdr_field hdr;
	
	if(msg==NULL) {
		if (res!=NULL) return -1;

		/* "fixup" call, res & msg are NULL */
		if (s->n <3) return -1;

		if (s->params[2].type==SEL_PARAM_STR) {
				/* replace _ with - (for P-xxx headers) */
			for (hi=s->params[2].v.s.len-1; hi>0; hi--)
				if (s->params[2].v.s.s[hi]=='_')
					s->params[2].v.s.s[hi]='-';
				/* if header name is parseable, parse it and set SEL_PARAM_DIV */
			c=s->params[2].v.s.s[s->params[2].v.s.len];
			s->params[2].v.s.s[s->params[2].v.s.len]=':';
			if (parse_hname2(s->params[2].v.s.s,s->params[2].v.s.s+(s->params[2].v.s.len<3?4:s->params[2].v.s.len+1),
						&hdr)==0) {
				ERR("select_anyhdr:fixup_call:parse error\n");
				return -1;
			}
			s->params[2].v.s.s[s->params[2].v.s.len]=c;
			
			if (hdr.type!=HDR_OTHER_T && hdr.type!=HDR_ERROR_T) {
				/* pkg_free(s->params[1].v.s.s); */
				/* don't free it (the mem can leak only once at startup)
				 * the parsed string can live inside larger string block
				 * e.g. when xlog's select is parsed
				 */
				s->params[2].type = SEL_PARAM_DIV;
				s->params[2].v.i = hdr.type;
			}
		}
		return 1;
	}

	hf0 = NULL;

	/* extract header index if present */
	if (s->param_offset[s->lvl+1] == 4) {
		if (s->params[3].type == SEL_PARAM_INT) {
			hi = s->params[3].v.i;
		} else {
			hi = -1;
		}
	} else {
		hi = 1;
	}

	/* we need to be sure we have parsed all headers */
	if (!msg->eoh && (parse_headers(msg,HDR_EOH_F,0)==-1 || !msg->eoh)) {
		ERR("bad msg while parsing to EOH \n");
		return -1;
	}
	for (hf=msg->headers; hf; hf=hf->next) {
		if(s->params[2].type==SEL_PARAM_DIV) {
			if (s->params[2].v.i!=hf->type)	continue;
		} else if(s->params[2].type==SEL_PARAM_STR) {
			if (s->params[2].v.s.len!=hf->name.len)	continue;
			if (strncasecmp(s->params[2].v.s.s, hf->name.s, hf->name.len)!=0) continue;
		}
		hf0 = hf;
		hi--;
		if (!hi) break;
	}
	if(hf0==NULL || hi>0)
		return 1;
	res->s = hf0->body.s;
	res->len = hf0->body.len;
	trim(res);
	return 0;
}
Esempio n. 17
0
void subs_cback_func(struct cell *t, int cb_type, struct tmcb_params *ps)
{
	struct sip_msg* msg= NULL;
	int lexpire= 0;
	unsigned int cseq;
	ua_pres_t* presentity= NULL, *hentity= NULL;
	struct to_body *pto = NULL, TO = {0}, *pfrom = NULL;
	int size= 0;
	unsigned int hash_code;
	int flag ;
	str record_route= {0, 0};
	int rt;
	str contact;
	int initial_request = 0;
	int end_transaction = 1;

	if( ps->param== NULL || *ps->param== NULL )
	{
		LM_ERR("null callback parameter\n");
		return;
	}

	if (dbmode == PUA_DB_ONLY && pua_dbf.start_transaction)
	{
		if (pua_dbf.start_transaction(pua_db) < 0)
		{
			LM_ERR("in start_transaction\n");
			goto error;
		}
	}

	LM_DBG("completed with status %d\n",ps->code) ;
	hentity= (ua_pres_t*)(*ps->param);
	hash_code= core_hash(hentity->pres_uri,hentity->watcher_uri,
				HASH_SIZE);
	flag= hentity->flag;
	if(hentity->flag & XMPP_INITIAL_SUBS)
		hentity->flag= XMPP_SUBSCRIBE;

	/* get dialog information from reply message: callid, to_tag, from_tag */
	msg= ps->rpl;
	if(msg == NULL)
	{
		LM_ERR("no reply message found\n ");
		goto error;
	}

	if(msg== FAKED_REPLY)
	{
		struct hdr_field *callid = NULL, *from = NULL;
		struct to_body FROM = {0};

		callid = (struct hdr_field *) pkg_malloc(sizeof(struct hdr_field));
		if (callid == NULL)
		{
			LM_ERR("Out of memory\n");
			goto faked_error;
		}
		memset(callid, 0, sizeof(struct hdr_field));
		get_hdr_field(t->callid.s, t->callid.s + t->callid.len, callid);
		hentity->call_id = callid->body;

		from = (struct hdr_field *) pkg_malloc(sizeof(struct hdr_field));
		if (from == NULL)
		{
			LM_ERR("Out of memory\n");
			goto faked_error;
		}
		memset(from, 0, sizeof(struct hdr_field));
		get_hdr_field(t->from.s, t->from.s + t->from.len, from);
		parse_to(from->body.s, from->body.s + from->body.len + 1, &FROM);
		if(FROM.uri.len <= 0) 
		{
			LM_ERR("'From' header NOT parsed\n");
			goto faked_error;
		}
	
		hentity->call_id = callid->body;
		hentity->from_tag = (&FROM)->tag_value;
		hentity->to_tag.s = NULL;
		hentity->to_tag.len = 0;

		find_and_delete_dialog(hentity, hash_code);
faked_error:
		if (callid) pkg_free(callid);
		free_to_params(&FROM);
		if (from) pkg_free(from);
		goto done;
	}
	
	if ( parse_headers(msg,HDR_EOH_F, 0)==-1 )
	{
		LM_ERR("when parsing headers\n");
		goto error;
	}

	if(ps->rpl->expires && msg->expires->body.len > 0)
	{
		if (!msg->expires->parsed && (parse_expires(msg->expires) < 0))
		{
			LM_ERR("cannot parse Expires header\n");
			goto error;
		}
		lexpire = ((exp_body_t*)msg->expires->parsed)->val;
		LM_DBG("lexpire= %d\n", lexpire);
	}

	/*if initial request */
	if(hentity->call_id.s== NULL)
	{
		initial_request = 1;

		if( msg->callid==NULL || msg->callid->body.s==NULL)
		{
			LM_ERR("cannot parse callid header\n");
			goto error;
		}
		
		if (!msg->from || !msg->from->body.s)
		{
			LM_ERR("cannot find 'from' header!\n");
			goto error;
		}
		if (msg->from->parsed == NULL)
		{
			if ( parse_from_header( msg )<0 ) 
			{
				LM_ERR("cannot parse From header\n");
				goto error;
			}
		}
		pfrom = (struct to_body*)msg->from->parsed;
	
		if( pfrom->tag_value.s ==NULL || pfrom->tag_value.len == 0)
		{
			LM_ERR("no from tag value present\n");
			goto error;
		}

		hentity->call_id=  msg->callid->body;
		hentity->from_tag= pfrom->tag_value;

		if(ps->code >= 300 || lexpire == 0)
		{
			hentity->to_tag.s = NULL;
			hentity->to_tag.len = 0;
			find_and_delete_dialog(hentity, hash_code);
			goto done;
		}

		if( msg->to==NULL || msg->to->body.s==NULL)
		{
			LM_ERR("cannot parse TO header\n");
			goto error;
		}			
		if(msg->to->parsed != NULL)
		{
			pto = (struct to_body*)msg->to->parsed;
			LM_DBG("'To' header ALREADY PARSED: <%.*s>\n",pto->uri.len,pto->uri.s);
		}
		else
		{
			parse_to(msg->to->body.s,msg->to->body.s +
				msg->to->body.len + 1, &TO);
			if(TO.uri.len <= 0) 
			{
				LM_ERR("'To' header NOT parsed\n");
				goto error;
			}
			pto = &TO;
		}			
		if( pto->tag_value.s ==NULL || pto->tag_value.len == 0)
		{
			LM_ERR("no to tag value present\n");
			goto error;
		}
		hentity->to_tag= pto->tag_value;
	}

	if(ps->code >= 300 )
	{	/* if an error code and a stored dialog delete it and try to send 
		   a subscription with type= INSERT_TYPE, else return*/	
		
		subs_info_t subs;

		hentity->to_tag.s = NULL;
		hentity->to_tag.len = 0;
		find_and_delete_dialog(hentity, hash_code);

		if (dbmode == PUA_DB_ONLY && pua_dbf.end_transaction)
		{
			if (pua_dbf.end_transaction(pua_db) < 0)
			{
				LM_ERR("in end_transaction\n");
				goto error;
			}
		}

		end_transaction = 0;

		/* Redirect if the response 3XX */
		memset(&subs, 0, sizeof(subs_info_t));
		subs.pres_uri= hentity->pres_uri; 
		subs.watcher_uri= hentity->watcher_uri;
		subs.contact= &hentity->contact;

		if(hentity->remote_contact.s)
			subs.remote_target= &hentity->remote_contact;

		if(hentity->desired_expires== 0)
			subs.expires= -1;
		else
		if(hentity->desired_expires< (int)time(NULL))
			subs.expires= 0;
		else
			subs.expires= hentity->desired_expires- (int)time(NULL)+ 3;

		subs.flag= INSERT_TYPE;
		subs.source_flag= flag;
		subs.event= hentity->event;
		subs.id= hentity->id;
		subs.outbound_proxy= hentity->outbound_proxy;
		subs.extra_headers= hentity->extra_headers;
		subs.cb_param= hentity->cb_param;
	
		if(send_subscribe(&subs)< 0)
		{
			LM_ERR("when trying to send SUBSCRIBE\n");
			goto error;
		}
		goto done;
	}

	if(lexpire== 0 )
	{
		LM_DBG("lexpire= 0 Delete from hash table");
		find_and_delete_dialog(hentity, hash_code);
		goto done;
	}

	/* extract the contact */
	if(msg->contact== NULL || msg->contact->body.s== NULL)
	{
		LM_ERR("no contact header found");
		goto error;
	}
	if( parse_contact(msg->contact) <0 )
	{
		LM_ERR(" cannot parse contact header\n");
		goto error;
	}
	if(msg->contact->parsed == NULL)
	{
		LM_ERR("cannot parse contact header\n");
		goto error;
	}
	contact = ((contact_body_t* )msg->contact->parsed)->contacts->uri;

	if( msg->cseq==NULL || msg->cseq->body.s==NULL)
	{
		LM_ERR("cannot parse cseq header\n");
		goto error;
	}

	if( str2int( &(get_cseq(msg)->number), &cseq)< 0)
	{
		LM_ERR("while converting str to int\n");
		goto error;
	}

	if(initial_request == 0)
	{
		hentity->cseq = cseq;
		find_and_update_dialog(hentity, hash_code, lexpire, &contact);
		goto done;
	}

	/*process record route and add it to a string*/
	if (msg->record_route!=NULL)
	{
		rt = print_rr_body(msg->record_route, &record_route, 1, 0);
		if(rt != 0)
		{
			LM_ERR("parsing record route [%d]\n", rt);	
			record_route.s=NULL;
			record_route.len=0;
		}
	}

	size= sizeof(ua_pres_t)+ 2*sizeof(str)+( pto->uri.len+
		pfrom->uri.len+ pto->tag_value.len+ pfrom->tag_value.len
		+msg->callid->body.len+ record_route.len+ hentity->contact.len+
		hentity->id.len )*sizeof(char);

	if(hentity->extra_headers)
		size+= sizeof(str)+ hentity->extra_headers->len*sizeof(char);

	presentity= (ua_pres_t*)shm_malloc(size);
	if(presentity== NULL)
	{
		LM_ERR("no more share memory\n");
		goto error;
	}
	
	memset(presentity, 0, size);
	size= sizeof(ua_pres_t);

	presentity->pres_uri= (str*)( (char*)presentity+ size);
	size+= sizeof(str);
	presentity->pres_uri->s= (char*)presentity+ size;
	memcpy(presentity->pres_uri->s, pto->uri.s, pto->uri.len);
	presentity->pres_uri->len= pto->uri.len;
	size+= pto->uri.len;

	presentity->watcher_uri= (str*)( (char*)presentity+ size);
	size+= sizeof(str);
	presentity->watcher_uri->s= (char*)presentity+ size;
	memcpy(presentity->watcher_uri->s, pfrom->uri.s, pfrom->uri.len);
	presentity->watcher_uri->len= pfrom->uri.len;
	size+= pfrom->uri.len;

	presentity->call_id.s= (char*)presentity + size;
	memcpy(presentity->call_id.s,msg->callid->body.s, 
		msg->callid->body.len);
	presentity->call_id.len= msg->callid->body.len;
	size+= presentity->call_id.len;

	presentity->to_tag.s= (char*)presentity + size;
	memcpy(presentity->to_tag.s,pto->tag_value.s, 
			pto->tag_value.len);
	presentity->to_tag.len= pto->tag_value.len;
	size+= pto->tag_value.len;

	presentity->from_tag.s= (char*)presentity + size;
	memcpy(presentity->from_tag.s,pfrom->tag_value.s, 
			pfrom->tag_value.len);
	presentity->from_tag.len= pfrom->tag_value.len;
	size+= pfrom->tag_value.len;

	if(record_route.len && record_route.s)
	{
		presentity->record_route.s= (char*)presentity + size;
		memcpy(presentity->record_route.s, record_route.s, record_route.len);
		presentity->record_route.len= record_route.len;
		size+= record_route.len;
		pkg_free(record_route.s);
	}

	presentity->contact.s= (char*)presentity + size;
	memcpy(presentity->contact.s, hentity->contact.s, hentity->contact.len);
	presentity->contact.len= hentity->contact.len;
	size+= hentity->contact.len;

	if(hentity->id.s)
	{
		presentity->id.s=(char*)presentity+ size;
		memcpy(presentity->id.s, hentity->id.s, 
			hentity->id.len);
		presentity->id.len= hentity->id.len; 
		size+= presentity->id.len;
	}

	if(hentity->extra_headers)
	{
		presentity->extra_headers= (str*)((char*)presentity+ size);
		size+= sizeof(str);
		presentity->extra_headers->s=(char*)presentity+ size;
		memcpy(presentity->extra_headers->s, hentity->extra_headers->s, 
			hentity->extra_headers->len);
		presentity->extra_headers->len= hentity->extra_headers->len; 
		size+= hentity->extra_headers->len;
	}

	/* write the remote contact filed */
	presentity->remote_contact.s= (char*)shm_malloc(contact.len* sizeof(char));
	if(presentity->remote_contact.s==NULL)
	{
		ERR_MEM(SHARE_MEM);
	}
	memcpy(presentity->remote_contact.s, contact.s, contact.len);
	presentity->remote_contact.len= contact.len;

	presentity->event|= hentity->event;
	presentity->flag= hentity->flag;
	presentity->etag.s= NULL;
	presentity->cseq= cseq;
	presentity->desired_expires= hentity->desired_expires;
	presentity->expires= lexpire+ (int)time(NULL);
	if(BLA_SUBSCRIBE & presentity->flag)
	{
		LM_DBG("BLA_SUBSCRIBE FLAG inserted\n");
	}	
	LM_DBG("record for subscribe from %.*s to %.*s inserted in datatbase\n",
			presentity->watcher_uri->len, presentity->watcher_uri->s,
			presentity->pres_uri->len, presentity->pres_uri->s);

	if (dbmode==PUA_DB_ONLY)
	{
		if (convert_temporary_dialog_puadb(presentity) < 0)
		{
			LM_ERR("Could not convert temporary dialog into a dialog\n");
			goto error;
		}
	}
	else
	{
		if (convert_temporary_dialog(presentity) < 0)
		{
			LM_ERR("Could not convert temporary dialog into a dialog\n");
			goto error;
		}
	}

done:
	if(hentity->ua_flag == REQ_OTHER)
	{
		hentity->flag= flag;
		run_pua_callbacks( hentity, msg);
	}

	if (dbmode == PUA_DB_ONLY && pua_dbf.end_transaction && end_transaction)
	{
		if (pua_dbf.end_transaction(pua_db) < 0)
		{
			LM_ERR("in end_transaction\n");
			goto error;
		}
	}

	goto end;

error:	
        if (presentity)
	{
		if (presentity->remote_contact.s) shm_free(presentity->remote_contact.s);
	 	shm_free(presentity);
	}

	if(record_route.s)
		pkg_free(record_route.s);

	if (dbmode == PUA_DB_ONLY && pua_dbf.abort_transaction)
	{
		if (pua_dbf.abort_transaction(pua_db) < 0)
			LM_ERR("in abort_transaction\n");
	}

end:

	if(hentity)
	{	
		shm_free(hentity);
		hentity= NULL;
	}

	free_to_params(&TO);
	return;
}
Esempio n. 18
0
/* authentication service
   return value:  -1: error
                  -2: message out of time
                  -3: Date header field does not match validity period of cert
                   1: success
*/
static int authservice_(struct sip_msg* msg, char* str1, char* str2)
{
	time_t dateHFValue = -1;
	int retval = 0;
	char dateHF[MAX_TIME] = "\0";
	long dateDelta = -1;

	/* parse all headers */
	if (parse_headers(msg, HDR_EOH_F, 0)!=0)
	{
		LM_ERR("failed to parse headers\n");
		return -1;
	}

	retval = getDate(dateHF, &dateHFValue, msg);

	switch(retval)
	{
		case 1:
			/* Date header field exists */
			dateDelta = getDateDelta(dateHFValue);
			if((dateDelta >= MAXDATEDELTA_AUTH) || dateDelta < 0)
			{
				return -2;
			}
			break;
		case 0:
			/* Date header field does not exist */
			if(!addDate(dateHF, &dateHFValue, msg))
			{
				LM_ERR("addDate failed\n");
				return -1;
			}
			break;
		case -1:
			LM_ERR("error reading Date header field\n");
			return -1;
			break;
	}

	if(!authCertMatchesDate(dateHFValue))
	{
		return -3;
	}

	/* is content len hdr found ?
	if(msg->content_length)
	{
		if(!addContentLength(msg))
		{
			LM_ERR("addContentLength failed\n");
			return -1;
		}
	}*/


	if(!addIdentity(dateHF, msg))
	{
		LM_ERR("addIdentity failed\n");
		return -1;
	}

	if(!addIdentityInfo(msg))
	{
		LM_ERR("addIdentityInfo failed\n");
		return -1;
	}

	return 1;
}
Esempio n. 19
0
static void
__dialog_cbtest(struct dlg_cell *dlg, int type, struct dlg_cb_params *_params)
{
	str tag;

	LM_DBG("dialog callback received, from=%.*s, to=%.*s\n",
		dlg->from_uri.len, dlg->from_uri.s, dlg->to_uri.len, dlg->to_uri.s);

	if (dlg->tag[0].len && dlg->tag[0].s ) {
		LM_DBG("dialog callback: tag[0] = %.*s\n",
			dlg->tag[0].len, dlg->tag[0].s);
	}
	if (dlg->tag[0].len && dlg->tag[1].s ) {
		LM_DBG("dialog callback: tag[1] = %.*s\n",
			dlg->tag[1].len, dlg->tag[1].s);
	}

	if (_params->msg && _params->msg!=FAKED_REPLY && type != DLGCB_DESTROY) {
		/* get to tag*/
		if ( !_params->msg->to) {
			/* to header not defined, parse to header */
			LM_DBG("to header not defined, parse to header\n");
			if (parse_headers(_params->msg, HDR_TO_F,0)<0) {
				/* parser error */
				LM_ERR("parsing of to-header failed\n");
				tag.s = 0;
				tag.len = 0;
			} else if (!_params->msg->to) {
				/* to header still not defined */
				LM_ERR("no to although to-header is parsed: bad reply "
					"or missing TO hdr :-/\n");
				tag.s = 0;
				tag.len = 0;
			} else 
				tag = get_to(_params->msg)->tag_value;
		} else {
			tag = get_to(_params->msg)->tag_value;
			if (tag.s==0 || tag.len==0) {
				LM_DBG("missing TAG param in TO hdr :-/\n");
				tag.s = 0;
				tag.len = 0;
			}
		}
		if (tag.s) {
			LM_DBG("dialog callback: _params->msg->to->parsed->tag_value "
				"= %.*s\n", tag.len, tag.s);
		}
	}

	switch (type) {
	case DLGCB_FAILED:
		LM_DBG("dialog callback type 'DLGCB_FAILED' received, from=%.*s\n",
			dlg->from_uri.len, dlg->from_uri.s);
		break;
	case DLGCB_CONFIRMED:
		LM_DBG("dialog callback type 'DLGCB_CONFIRMED' received, from=%.*s\n",
			dlg->from_uri.len, dlg->from_uri.s);
		break;
	case DLGCB_REQ_WITHIN:
		LM_DBG("dialog callback type 'DLGCB_REQ_WITHIN' received, from=%.*s\n",
			dlg->from_uri.len, dlg->from_uri.s);
		break;
	case DLGCB_TERMINATED:
		LM_DBG("dialog callback type 'DLGCB_TERMINATED' received, from=%.*s\n",
			dlg->from_uri.len, dlg->from_uri.s);
		break;
	case DLGCB_EXPIRED:
		LM_DBG("dialog callback type 'DLGCB_EXPIRED' received, from=%.*s\n",
			dlg->from_uri.len, dlg->from_uri.s);
		break;
	case DLGCB_EARLY:
		LM_DBG("dialog callback type 'DLGCB_EARLY' received, from=%.*s\n",
			dlg->from_uri.len, dlg->from_uri.s);
		break;
	case DLGCB_RESPONSE_FWDED:
		LM_DBG("dialog callback type 'DLGCB_RESPONSE_FWDED' received, "
			"from=%.*s\n", dlg->from_uri.len, dlg->from_uri.s);
		break;
	case DLGCB_RESPONSE_WITHIN:
		LM_DBG("dialog callback type 'DLGCB_RESPONSE_WITHIN' received, "
			"from=%.*s\n", dlg->from_uri.len, dlg->from_uri.s);
		break;
	case DLGCB_MI_CONTEXT:
		LM_DBG("dialog callback type 'DLGCB_MI_CONTEXT' received, from=%.*s\n",
			dlg->from_uri.len, dlg->from_uri.s);
		break;
	case DLGCB_DESTROY:
		LM_DBG("dialog callback type 'DLGCB_DESTROY' received, from=%.*s\n",
			dlg->from_uri.len, dlg->from_uri.s);
		break;
	default:
		LM_DBG("dialog callback type 'unknown' received, from=%.*s\n",
			dlg->from_uri.len, dlg->from_uri.s);
	}
}
Esempio n. 20
0
void subs_cback_func(struct cell *t, int cb_type, struct tmcb_params *ps)
{
	struct sip_msg* msg= NULL;
	int lexpire= 0;
	unsigned int cseq;
	ua_pres_t* presentity= NULL, *hentity= NULL;
	struct to_body *pto= NULL, *pfrom = NULL;
	int size= 0;
	int flag ;
	str record_route= {0, 0};
	int rt;
	str contact;
	int initial_request = 0;

	if(ps==NULL || ps->param== NULL || *ps->param== NULL )
	{
		LM_ERR("null callback parameter\n");
		return;
	}
	LM_DBG("completed with status %d\n",ps->code) ;
	hentity= (ua_pres_t*)(*ps->param);
	flag= hentity->flag;
	if(hentity->flag & XMPP_INITIAL_SUBS)
		hentity->flag= XMPP_SUBSCRIBE;

	/* get dialog information from reply message: callid, to_tag, from_tag */
	msg= ps->rpl;
	if(msg == NULL)
	{
		LM_ERR("no reply message found\n ");
		goto error;
	}

	if(msg== FAKED_REPLY)
	{
		/* delete record from hash_table and call registered functions */

		if(hentity->call_id.s== NULL) /* if a new requets failed-> do nothing*/
		{
			LM_DBG("initial Subscribe request failed\n");
			goto done;
		}
		lock_get(&HashT->p_records[hentity->hash_index].lock);
		presentity = get_htable_safe(hentity->hash_index, hentity->local_index);
		if(presentity)
		{
			delete_htable_safe(presentity, hentity->hash_index);
			lock_release(&HashT->p_records[hentity->hash_index].lock);
		}
		lock_release(&HashT->p_records[hentity->hash_index].lock);
		goto done;
	}

	if ( parse_headers(msg,HDR_EOH_F, 0)==-1 )
	{
		LM_ERR("when parsing headers\n");
		goto done;
	}

	/*if initial request */

	if(hentity->call_id.s== NULL)
	{
		initial_request = 1;
		if(ps->code>= 300)
		{
			LM_DBG("initial Subscribe request failed\n");
			goto done;
		}

		if( msg->callid==NULL || msg->callid->body.s==NULL)
		{
			LM_ERR("cannot parse callid header\n");
			goto done;
		}

		if (!msg->from || !msg->from->body.s)
		{
			LM_ERR("cannot find 'from' header!\n");
			goto done;
		}
		if (msg->from->parsed == NULL)
		{
			if ( parse_from_header( msg )<0 ) 
			{
				LM_ERR("cannot parse From header\n");
				goto done;
			}
		}
		pfrom = (struct to_body*)msg->from->parsed;

		if( pfrom->tag_value.s ==NULL || pfrom->tag_value.len == 0)
		{
			LM_ERR("no from tag value present\n");
			goto done;
		}
		if( msg->to==NULL || msg->to->body.s==NULL)
		{
			LM_ERR("cannot parse TO header\n");
			goto done;
		}

		pto = get_to(msg);
		if (pto == NULL || pto->error != PARSE_OK) {
			LM_ERR("failed to parse TO header\n");
			goto done;
		}

		if( pto->tag_value.s ==NULL || pto->tag_value.len == 0)
		{
			LM_ERR("no to tag value present\n");
			goto done;
		}
		hentity->call_id=  msg->callid->body;
		hentity->to_tag= pto->tag_value;
		hentity->from_tag= pfrom->tag_value;

	}

	/* extract the other necesary information for inserting a new record */
	if(ps->rpl->expires && msg->expires->body.len > 0)
	{
		if (!msg->expires->parsed && (parse_expires(msg->expires) < 0))
		{
			LM_ERR("cannot parse Expires header\n");
			goto done;
		}
		lexpire = ((exp_body_t*)msg->expires->parsed)->val;
		LM_DBG("lexpire= %d\n", lexpire);
	}

	if(ps->code >= 300 )
	{	/* if an error code and a stored dialog delete it and try to send 
		   a subscription with type= INSERT_TYPE, else return*/

		if(!initial_request)
		{
			subs_info_t subs;

			lock_get(&HashT->p_records[hentity->hash_index].lock);
			presentity = get_htable_safe(hentity->hash_index, hentity->local_index);
			if(presentity)
			{
				hentity->event= presentity->event;
				delete_htable_safe(presentity, hentity->hash_index);
				lock_release(&HashT->p_records[hentity->hash_index].lock);
			}
			lock_release(&HashT->p_records[hentity->hash_index].lock);

			memset(&subs, 0, sizeof(subs_info_t));
			subs.pres_uri= hentity->pres_uri;
			subs.to_uri  = hentity->to_uri;
			subs.watcher_uri= hentity->watcher_uri;
			subs.contact= &hentity->contact;

			if(hentity->remote_contact.s)
				subs.remote_target= &hentity->remote_contact;

			if(hentity->desired_expires== 0)
				subs.expires= -1;
			else
			if(hentity->desired_expires< (int)time(NULL))
				subs.expires= 0;
			else
				subs.expires= hentity->desired_expires- (int)time(NULL)+ 3;

			subs.flag= INSERT_TYPE;
			subs.source_flag= flag;
			subs.event= hentity->event;
			subs.id= hentity->id;
			subs.outbound_proxy= hentity->outbound_proxy;
			subs.extra_headers= &hentity->extra_headers;
			subs.cb_param= hentity->cb_param;

			if(send_subscribe(&subs)< 0)
			{
				LM_ERR("when trying to send SUBSCRIBE\n");
				goto done;
			}
		}
		goto done;
	}
	/*if a 2XX reply handle the two cases- an existing dialog and a new one*/

	/* extract the contact */
	if(msg->contact== NULL || msg->contact->body.s== NULL)
	{
		LM_ERR("no contact header found");
		goto error;
	}
	if( parse_contact(msg->contact) <0 )
	{
		LM_ERR(" cannot parse contact header\n");
		goto error;
	}

	if(msg->contact->parsed == NULL)
	{
		LM_ERR("cannot parse contact header\n");
		goto error;
	}
	contact = ((contact_body_t* )msg->contact->parsed)->contacts->uri;

	if(!initial_request)
	{
		/* do not delete the dialog - allow Notifies to be recognized as
		 * inside a known dialog */
	        if (lexpire == 0)
	                lexpire = 5;

		LM_DBG("*** Update expires\n");
		update_htable(hentity->hash_index, hentity->local_index, lexpire, NULL, &contact);
		goto done;
	}

	/* if a new dialog -> insert */
	if(lexpire== 0)
	{
		LM_DBG("expires= 0: no not insert\n");
		goto done;
	}

	if( msg->cseq==NULL || msg->cseq->body.s==NULL)
	{
		LM_ERR("cannot parse cseq header\n");
		goto done;
	}

	if( str2int( &(get_cseq(msg)->number), &cseq)< 0)
	{
		LM_ERR("while converting str to int\n");
		goto done;
    }

	/*process record route and add it to a string*/
	if (msg->record_route!=NULL)
	{
		rt = print_rr_body(msg->record_route, &record_route, 1, 0);
		if(rt != 0)
		{
			LM_ERR("parsing record route [%d]\n", rt);
			record_route.s=NULL;
			record_route.len=0;
		}
	}

	size= sizeof(ua_pres_t)+ 2*sizeof(str)+(hentity->pres_uri->len+ pto->uri.len+
		pfrom->uri.len+ pto->tag_value.len+ pfrom->tag_value.len
		+msg->callid->body.len+ record_route.len+ hentity->contact.len+
		hentity->id.len )*sizeof(char);

	presentity= (ua_pres_t*)shm_malloc(size);
	if(presentity== NULL)
	{
		LM_ERR("no more share memory\n");
		if(record_route.s)
			pkg_free(record_route.s);
		goto done;
	}
	memset(presentity, 0, size);
	size= sizeof(ua_pres_t);

	presentity->pres_uri= (str*)( (char*)presentity+ size);
	size+= sizeof(str);
	presentity->pres_uri->s= (char*)presentity+ size;
	memcpy(presentity->pres_uri->s, hentity->pres_uri->s, hentity->pres_uri->len);
	presentity->pres_uri->len= hentity->pres_uri->len;
	size+= hentity->pres_uri->len;

	presentity->to_uri.s= (char*)presentity+ size;
	memcpy(presentity->to_uri.s, pto->uri.s, pto->uri.len);
	presentity->to_uri.len= pto->uri.len;
	size+= pto->uri.len;

	presentity->watcher_uri= (str*)( (char*)presentity+ size);
	size+= sizeof(str);
	presentity->watcher_uri->s= (char*)presentity+ size;
	memcpy(presentity->watcher_uri->s, pfrom->uri.s, pfrom->uri.len);
	presentity->watcher_uri->len= pfrom->uri.len;
	size+= pfrom->uri.len;

	presentity->call_id.s= (char*)presentity + size;
	memcpy(presentity->call_id.s,msg->callid->body.s, 
		msg->callid->body.len);
	presentity->call_id.len= msg->callid->body.len;
	size+= presentity->call_id.len;

	presentity->to_tag.s= (char*)presentity + size;
	memcpy(presentity->to_tag.s,pto->tag_value.s, 
			pto->tag_value.len);
	presentity->to_tag.len= pto->tag_value.len;
	size+= pto->tag_value.len;

	presentity->from_tag.s= (char*)presentity + size;
	memcpy(presentity->from_tag.s,pfrom->tag_value.s, 
			pfrom->tag_value.len);
	presentity->from_tag.len= pfrom->tag_value.len;
	size+= pfrom->tag_value.len;

	if(record_route.len && record_route.s)
	{
		presentity->record_route.s= (char*)presentity + size;
		memcpy(presentity->record_route.s, record_route.s, record_route.len);
		presentity->record_route.len= record_route.len;
		size+= record_route.len;
		pkg_free(record_route.s);
	}


	presentity->contact.s= (char*)presentity + size;
	memcpy(presentity->contact.s, hentity->contact.s, hentity->contact.len);
	presentity->contact.len= hentity->contact.len;
	size+= hentity->contact.len;

	if(hentity->id.s)
	{
		presentity->id.s=(char*)presentity+ size;
		memcpy(presentity->id.s, hentity->id.s, 
			hentity->id.len);
		presentity->id.len= hentity->id.len; 
		size+= presentity->id.len;
	}

	if(hentity->extra_headers.s && hentity->extra_headers.len)
	{
		presentity->extra_headers.s= (char*)shm_malloc(hentity->extra_headers.len* sizeof(char));
		if(presentity->extra_headers.s== NULL)
		{
			ERR_MEM(SHARE_MEM);
		}
		memcpy(presentity->extra_headers.s, hentity->extra_headers.s, hentity->extra_headers.len);
		presentity->extra_headers.len= hentity->extra_headers.len;
	}

	/* write the remote contact filed */
	presentity->remote_contact.s= (char*)shm_malloc(contact.len* sizeof(char));
	if(presentity->remote_contact.s== NULL)
	{
		ERR_MEM(SHARE_MEM);
	}
	memcpy(presentity->remote_contact.s, contact.s, contact.len);
	presentity->remote_contact.len= contact.len;

	presentity->event|= hentity->event;
	presentity->flag= hentity->flag;
	presentity->etag.s= NULL;
	presentity->cseq= cseq;
	presentity->desired_expires= hentity->desired_expires;
	presentity->expires= lexpire+ (int)time(NULL);
	if(BLA_SUBSCRIBE & presentity->flag)
	{
		LM_DBG("BLA_SUBSCRIBE FLAG inserted\n");
	}
	LM_DBG("record for subscribe from %.*s to %.*s inserted in datatbase\n",
			presentity->watcher_uri->len, presentity->watcher_uri->s,
			presentity->pres_uri->len, presentity->pres_uri->s);
	insert_htable(presentity);

done:
	if(hentity->ua_flag == REQ_OTHER)
	{
		hentity->flag= flag;
		run_pua_callbacks( hentity, msg);
	}
error:
	if(hentity)
	{
		if(presentity->extra_headers.s) shm_free(presentity->extra_headers.s);
		if(presentity->remote_contact.s) shm_free(presentity->remote_contact.s);
		shm_free(hentity);
		hentity= NULL;
	}
	return;
}
/*
 * Add the sdp carried by the given SIP message into the qos context.
 */
void add_sdp(qos_ctx_t *qos_ctx, unsigned int dir, struct sip_msg *_m, unsigned int role, unsigned int other_role)
{
	qos_sdp_t *qos_sdp;
	sdp_session_cell_t *recv_session;
	str *cseq_number, *cseq_method;
	int cseq_method_id, sdp_match;

	if ( (!_m->cseq && parse_headers(_m,HDR_CSEQ_F,0)<0) || !_m->cseq || !_m->cseq->parsed) {
		LM_ERR("bad sip message or missing CSeq hdr\n");
		return;
	}

	cseq_number = &((get_cseq(_m))->number);
	cseq_method = &((get_cseq(_m))->method);
	cseq_method_id = (get_cseq(_m))->method_id;

	LM_DBG("cseq=`%.*s' `%.*s' and dir=%d\n",
		cseq_number->len, cseq_number->s,
		cseq_method->len, cseq_method->s, dir);

	/* Let's iterate through all the received sessions */
	recv_session = ((sdp_info_t*)_m->body)->sessions;
	while(recv_session) {
		qos_sdp = NULL;
		sdp_match = find_qos_sdp(qos_ctx, dir, other_role, cseq_number, cseq_method_id, recv_session, _m, &qos_sdp);

		switch (sdp_match) {
			case NO_INVITE_REQ_MATCH:
				if (0!=add_pending_sdp_session( qos_ctx, dir, cseq_number, cseq_method, cseq_method_id, role, N_INVITE_200OK, recv_session, _m)) {
					LM_ERR("Unable to add new sdp session\n");
					goto error;
				}

				break;
			case NO_INVITE_RESP_MATCH:
				if (0!=add_pending_sdp_session( qos_ctx, dir, cseq_number, cseq_method, cseq_method_id, role, N_200OK_ACK, recv_session, _m)) {
					LM_ERR("Unable to add new sdp session\n");
					goto error;
				}

				break;
			case ERROR_MATCH:
			case NO_ACK_REQ_MATCH:
			case NO_UPDATE_REQ_MATCH:
			case NO_UPDATE_RESP_MATCH:
				LM_ERR("error match: %d\n", sdp_match);
				break;
			case PENDING_MATCH:
				LM_DBG("we have a pending match: %p\n", qos_sdp);
				/* Let's save the received session */
				qos_sdp->sdp_session[role] = clone_sdp_session_cell(recv_session);
				if (qos_sdp->sdp_session[role] == NULL) {
					LM_ERR("PENDING_MATCH:oom: Unable to add new sdp session\n");
					return;
				}

				/* Negotiation completed, need to move the established SDP into the negotiated_sdp */

				/* removing qos_sdp from qos_ctx->pending_sdp list */
				unlink_pending_qos_sdp(qos_ctx, qos_sdp);
				/* inserting qos_sdp into the qos_ctx->negotiated_sdp list */
				link_negotiated_qos_sdp_and_run_cb(qos_ctx, qos_sdp, role, _m);

				break;
			case NEGOTIATED_MATCH:
				LM_DBG("we have a negotiated match: %p\n", qos_sdp);
				/* some sanity checks */
				if (qos_sdp->sdp_session[role]) {
					free_cloned_sdp_session(qos_sdp->sdp_session[role]);
				} else {
					LM_ERR("missing sdp_session for %s\n", (role==QOS_CALLER)?"QOS_CALLER":"QOS_CALLEE");
				}
				/* Let's save the received session */
				qos_sdp->sdp_session[role] = clone_sdp_session_cell(recv_session);
				if (qos_sdp->sdp_session[role]  == NULL) {
					LM_ERR("NEGOTIATED_MATCH:oom: Unable to add new sdp session\n");
					return;
				}

				LM_DBG("run_qos_callbacks(QOSCB_UPDATE_SDP, qos_ctx=%p, qos_sdp=%p, role=%d, _m=%p)\n",
					qos_ctx, qos_sdp, role, _m);
				run_qos_callbacks(QOSCB_UPDATE_SDP, qos_ctx, qos_sdp, role, _m);

				break;
			default:
				LM_CRIT("Undefined return code from find_qos_sdp(): %d\n", sdp_match);
		}
		recv_session = recv_session->next;
	}

	return;
error:
	shm_free(qos_sdp);
	LM_DBG("free qos_sdp: %p\n", qos_sdp);
	return;
}
Esempio n. 22
0
/**
 * Force Service routes (upon request)
 */
int force_service_routes(struct sip_msg* _m, udomain_t* _d) {
	struct hdr_field *it;
	int i;
	str new_route_header;
	struct lump* lmp = NULL;
	char * buf;
	pcontact_t * c = getContactP(_m, _d);
	char srcip[20];
	str received_host;
	
	// Contact not found => not following service-routes
	if (c == NULL) return -1;

	/* we need to be sure we have seen all HFs */
	parse_headers(_m, HDR_EOH_F, 0);

	/* Save current buffer */
	buf = _m->buf;

	// Delete old Route headers:
	if (_m->route) {
		for (it = _m->route; it; it = it->next) {
			if (it->type == HDR_ROUTE_T) {
				if ((lmp = del_lump(_m, it->name.s - buf, it->len, HDR_ROUTE_T)) == 0) {
					LM_ERR("del_lump failed \n");
					return -1;
				}
			}
		}
	}

	/* Reset dst_uri if previously set either by loose route or manually */
	if (_m->dst_uri.s && _m->dst_uri.len) {
		pkg_free(_m->dst_uri.s);
		_m->dst_uri.s = NULL;
		_m->dst_uri.len = 0;
	}
	
	received_host.len = ip_addr2sbuf(&_m->rcv.src_ip, srcip, sizeof(srcip));
	received_host.s = srcip;

	/* Lock this record while working with the data: */
	ul.lock_udomain(_d, &c->aor, &received_host, _m->rcv.src_port);

	if (c->num_service_routes > 0) {
		/* Create anchor for new Route-Header: */
		lmp = anchor_lump(_m, _m->headers->name.s - buf,0,0);
		if (lmp == 0) {
			LM_ERR("Failed to get anchor lump\n");
			goto error;
		}	
		/* Calculate the length: */
		new_route_header.len = route_start.len +
			route_end.len + (c->num_service_routes-1) * route_sep.len;

		for(i=0; i< c->num_service_routes; i++)
			new_route_header.len+=c->service_routes[i].len;		
		/* Allocate the memory for this new header: */
		new_route_header.s = pkg_malloc(new_route_header.len);
		if (!new_route_header.s) {
			LM_ERR("Error allocating %d bytes\n", new_route_header.len);
			goto error;
		}
		
		/* Construct new header */
		new_route_header.len = 0;
		STR_APPEND(new_route_header, route_start);
		for(i=0; i < c->num_service_routes; i++) {
			if (i) STR_APPEND(new_route_header, route_sep);
			STR_APPEND(new_route_header, c->service_routes[i]);
		}
		STR_APPEND(new_route_header, route_end);

		LM_DBG("Setting route header to <%.*s> \n", new_route_header.len, new_route_header.s);

		if ((lmp = insert_new_lump_after(lmp, new_route_header.s, new_route_header.len, HDR_ROUTE_T)) == 0) {
			LM_ERR("Error inserting new route set\n");
			pkg_free(new_route_header.s);
			goto error;
		}

		LM_DBG("Setting dst_uri to <%.*s> \n", c->service_routes[0].len,
			c->service_routes[0].s);

		if (set_dst_uri(_m, &c->service_routes[0]) !=0 ) {
			LM_ERR("Error setting new dst uri\n");
			goto error;
		}
	}
	/* Unlock domain */
	ul.unlock_udomain(_d, &c->aor, &received_host, _m->rcv.src_port);
	return 1;
error:
	/* Unlock domain */
	ul.unlock_udomain(_d, &c->aor, &received_host, _m->rcv.src_port);
	return -1;
	
}
Esempio n. 23
0
int ws_handle_handshake(struct sip_msg *msg)
{
	str key = {0, 0}, headers = {0, 0}, reply_key = {0, 0}, origin = {0, 0};
	unsigned char sha1[SHA_DIGEST_LENGTH];
	unsigned int hdr_flags = 0, sub_protocol = 0;
	int version = 0;
	struct hdr_field *hdr = msg->headers;
	struct tcp_connection *con;
	ws_connection_t *wsc;

	/* Make sure that the connection is closed after the response _and_
	   the existing connection (from the request) is reused for the
	   response.  The close flag will be unset later if the handshake is
	   successful. */
	msg->rpl_send_flags.f |= SND_F_CON_CLOSE;
	msg->rpl_send_flags.f |= SND_F_FORCE_CON_REUSE;

	if (cfg_get(websocket, ws_cfg, enabled) == 0)
	{
		LM_INFO("disabled: bouncing handshake\n");
		ws_send_reply(msg, 503, &str_status_service_unavailable,
				NULL);
		return 0;
	}

	/* Retrieve TCP/TLS connection */
	if ((con = tcpconn_get(msg->rcv.proto_reserved1, 0, 0, 0, 0)) == NULL)
	{
		LM_ERR("retrieving connection\n");
		ws_send_reply(msg, 500, &str_status_internal_server_error,
				NULL);
		return 0;
	}

	if (con->type != PROTO_TCP && con->type != PROTO_TLS)
	{
		LM_ERR("unsupported transport: %d", con->type);
		goto end;
	}

	if (parse_headers(msg, HDR_EOH_F, 0) < 0)
	{
		LM_ERR("error parsing headers\n");
		ws_send_reply(msg, 500, &str_status_internal_server_error,
				NULL);
		goto end;
	}

	/* Process HTTP headers */
	while (hdr != NULL)
	{
		/* Decode and validate Connection */
		if (cmp_hdrname_strzn(&hdr->name,
				str_hdr_connection.s,
				str_hdr_connection.len) == 0)
		{
			strlower(&hdr->body);
			if (str_search(&hdr->body, &str_upgrade) != NULL)
			{
				LM_DBG("found %.*s: %.*s\n",

					hdr->name.len, hdr->name.s,
					hdr->body.len, hdr->body.s);
				hdr_flags |= CONNECTION;
			}
		}
		/* Decode and validate Upgrade */
		else if (cmp_hdrname_strzn(&hdr->name,
				str_hdr_upgrade.s,
				str_hdr_upgrade.len) == 0)
		{
			strlower(&hdr->body);
			if (str_search(&hdr->body, &str_websocket) != NULL)
			{
				LM_DBG("found %.*s: %.*s\n",
					hdr->name.len, hdr->name.s,
					hdr->body.len, hdr->body.s);
				hdr_flags |= UPGRADE;
			}
		}
		/* Decode and validate Sec-WebSocket-Key */
		else if (cmp_hdrname_strzn(&hdr->name,
				str_hdr_sec_websocket_key.s, 
				str_hdr_sec_websocket_key.len) == 0) 
		{
			if (hdr_flags & SEC_WEBSOCKET_KEY)
			{
				LM_WARN("%.*s found multiple times\n",
					hdr->name.len, hdr->name.s);
				ws_send_reply(msg, 400,
						&str_status_bad_request,
						NULL);
				goto end;
			}

			LM_DBG("found %.*s: %.*s\n",
				hdr->name.len, hdr->name.s,
				hdr->body.len, hdr->body.s);
			key = hdr->body;
			hdr_flags |= SEC_WEBSOCKET_KEY;
		}
		/* Decode and validate Sec-WebSocket-Protocol */
		else if (cmp_hdrname_strzn(&hdr->name,
				str_hdr_sec_websocket_protocol.s,
				str_hdr_sec_websocket_protocol.len) == 0)
		{
			strlower(&hdr->body);
			if (str_search(&hdr->body, &str_sip) != NULL)
			{
				LM_DBG("found %.*s: %.*s\n",
					hdr->name.len, hdr->name.s,
					hdr->body.len, hdr->body.s);
				hdr_flags |= SEC_WEBSOCKET_PROTOCOL;
				sub_protocol |= SUB_PROTOCOL_SIP;
			}
			if (str_search(&hdr->body, &str_msrp) != NULL)
			{
				LM_DBG("found %.*s: %.*s\n",
					hdr->name.len, hdr->name.s,
					hdr->body.len, hdr->body.s);
				hdr_flags |= SEC_WEBSOCKET_PROTOCOL;
				sub_protocol |= SUB_PROTOCOL_MSRP;
			}
		}
		/* Decode and validate Sec-WebSocket-Version */
		else if (cmp_hdrname_strzn(&hdr->name,
				str_hdr_sec_websocket_version.s,
				str_hdr_sec_websocket_version.len) == 0)
		{
			if (hdr_flags & SEC_WEBSOCKET_VERSION)
			{
				LM_WARN("%.*s found multiple times\n",
					hdr->name.len, hdr->name.s);
				ws_send_reply(msg, 400,
						&str_status_bad_request,
						NULL);
				goto end;
			}

			str2sint(&hdr->body, &version);

			if (version != WS_VERSION)
			{
				LM_WARN("Unsupported protocol version %.*s\n",
					hdr->body.len, hdr->body.s);
				headers.s = headers_buf;
				headers.len = snprintf(headers.s, HDR_BUF_LEN,
					"%.*s: %d\r\n",
					str_hdr_sec_websocket_version.len,
					str_hdr_sec_websocket_version.s,
					WS_VERSION);
				ws_send_reply(msg, 426,
						&str_status_upgrade_required,
						&headers);
				goto end;
			}

			LM_DBG("found %.*s: %.*s\n",
				hdr->name.len, hdr->name.s,
				hdr->body.len, hdr->body.s);
			hdr_flags |= SEC_WEBSOCKET_VERSION;
		}
		/* Decode Origin */
		else if (cmp_hdrname_strzn(&hdr->name,
				str_hdr_origin.s,
				str_hdr_origin.len) == 0)
		{
			if (hdr_flags & ORIGIN)
			{
				LM_WARN("%.*s found multiple times\n",
					hdr->name.len, hdr->name.s);
				ws_send_reply(msg, 400,
						&str_status_bad_request,
						NULL);
				goto end;
			}

			LM_DBG("found %.*s: %.*s\n",
				hdr->name.len, hdr->name.s,
				hdr->body.len, hdr->body.s);
			origin = hdr->body;
			hdr_flags |= ORIGIN;
		}

		hdr = hdr->next;
	}

	/* Final check that all required headers/values were found */
	sub_protocol &= ws_sub_protocols;
	if ((hdr_flags & REQUIRED_HEADERS) != REQUIRED_HEADERS
			|| sub_protocol == 0)
	{

		LM_WARN("required headers not present\n");
		headers.s = headers_buf;
		headers.len = 0;

		if (ws_sub_protocols & SUB_PROTOCOL_SIP)
			headers.len += snprintf(headers.s + headers.len,
						HDR_BUF_LEN - headers.len,
						"%.*s: %.*s\r\n",
					str_hdr_sec_websocket_protocol.len,
					str_hdr_sec_websocket_protocol.s,
					str_sip.len, str_sip.s);

		if (ws_sub_protocols & SUB_PROTOCOL_MSRP)
			headers.len += snprintf(headers.s + headers.len,
						HDR_BUF_LEN - headers.len,
						"%.*s: %.*s\r\n",
					str_hdr_sec_websocket_protocol.len,
					str_hdr_sec_websocket_protocol.s,
					str_msrp.len, str_msrp.s);

		headers.len += snprintf(headers.s + headers.len,
					HDR_BUF_LEN - headers.len,
					"%.*s: %d\r\n",
					str_hdr_sec_websocket_version.len,
					str_hdr_sec_websocket_version.s,
					WS_VERSION);
		ws_send_reply(msg, 400, &str_status_bad_request, &headers);
		goto end;
	}

	/* Construct reply_key */
	reply_key.s = (char *) pkg_malloc(
				(key.len + str_ws_guid.len) * sizeof(char)); 
	if (reply_key.s == NULL)
	{
		LM_ERR("allocating pkg memory\n");
		ws_send_reply(msg, 500, &str_status_internal_server_error,
				NULL);
		goto end;
	}
	memcpy(reply_key.s, key.s, key.len);
	memcpy(reply_key.s + key.len, str_ws_guid.s, str_ws_guid.len);
	reply_key.len = key.len + str_ws_guid.len;
	SHA1((const unsigned char *) reply_key.s, reply_key.len, sha1);
	pkg_free(reply_key.s);
	reply_key.s = key_buf;
	reply_key.len = base64_enc(sha1, SHA_DIGEST_LENGTH,
				(unsigned char *) reply_key.s,
				base64_enc_len(SHA_DIGEST_LENGTH));

	/* Add the connection to the WebSocket connection table */
	wsconn_add(msg->rcv, sub_protocol);

	/* Make sure Kamailio core sends future messages on this connection
	   directly to this module */
	if (con->type == PROTO_TLS)
		con->type = con->rcv.proto = PROTO_WSS;
	else
		con->type = con->rcv.proto = PROTO_WS;

	/* Now Kamailio is ready to receive WebSocket frames build and send a
	   101 reply */
	headers.s = headers_buf;
	headers.len = 0;

	if (ws_cors_mode == CORS_MODE_ANY)
		headers.len += snprintf(headers.s + headers.len,
					HDR_BUF_LEN - headers.len,
					"%.*s: *\r\n",
					str_hdr_access_control_allow_origin.len,
					str_hdr_access_control_allow_origin.s);
	else if (ws_cors_mode == CORS_MODE_ORIGIN && origin.len > 0)
		headers.len += snprintf(headers.s + headers.len,
					HDR_BUF_LEN - headers.len,
					"%.*s: %.*s\r\n",
					str_hdr_access_control_allow_origin.len,
					str_hdr_access_control_allow_origin.s,
					origin.len,
					origin.s);

	if (sub_protocol & SUB_PROTOCOL_SIP)
		headers.len += snprintf(headers.s + headers.len,
					HDR_BUF_LEN - headers.len,
					"%.*s: %.*s\r\n",
					str_hdr_sec_websocket_protocol.len,
					str_hdr_sec_websocket_protocol.s,
					str_sip.len, str_sip.s);
	else if (sub_protocol & SUB_PROTOCOL_MSRP)
		headers.len += snprintf(headers.s + headers.len,
					HDR_BUF_LEN - headers.len,
					"%.*s: %.*s\r\n",
					str_hdr_sec_websocket_protocol.len,
					str_hdr_sec_websocket_protocol.s,
					str_msrp.len, str_msrp.s);

	headers.len += snprintf(headers.s + headers.len,
				HDR_BUF_LEN - headers.len,
				"%.*s: %.*s\r\n"
				"%.*s: %.*s\r\n"
				"%.*s: %.*s\r\n",
				str_hdr_upgrade.len, str_hdr_upgrade.s,
				str_websocket.len, str_websocket.s,
				str_hdr_connection.len, str_hdr_connection.s,
				str_upgrade.len, str_upgrade.s,
				str_hdr_sec_websocket_accept.len,
				str_hdr_sec_websocket_accept.s, reply_key.len,
				reply_key.s);
	msg->rpl_send_flags.f &= ~SND_F_CON_CLOSE;
	if (ws_send_reply(msg, 101, &str_status_switching_protocols,
				&headers) < 0)
	{
		if ((wsc = wsconn_get(msg->rcv.proto_reserved1)) != NULL)
		{
			wsconn_rm(wsc, WSCONN_EVENTROUTE_NO);
			wsconn_put(wsc);
		}
		goto end;
	}
	else
	{
		if (sub_protocol & SUB_PROTOCOL_SIP)
			update_stat(ws_sip_successful_handshakes, 1);
		else if (sub_protocol & SUB_PROTOCOL_MSRP)
			update_stat(ws_msrp_successful_handshakes, 1);
	}

	tcpconn_put(con);
	return 1;
end:
	if (con)
		tcpconn_put(con);
	return 0;
}
Esempio n. 24
0
boost::optional<http_request_header> http_header_parser::parse_request_header(std::string::const_iterator begin, std::string::const_iterator end)
{
    auto iter = begin;
    auto tmp = iter;
    for (;iter != end && *iter != ' ' && *iter != '\r'; ++iter)
        ;
    if (iter == tmp || iter == end || *iter != ' ') return nullptr;
    http_request_header header;
    header._method = std::string(tmp, iter);
    tmp = ++iter;
    for (;iter != end && *iter != ' ' && *iter != '\r'; ++iter)
        ;
    if (iter == tmp || iter == end || *iter != ' ') return nullptr;
    auto request_uri = std::string(tmp, iter);
    if (header.method() == "CONNECT") {
        boost::regex regex("(.+?):(\\d+)");
        boost::match_results<std::string::iterator> match_results;
        if (!boost::regex_match(request_uri.begin(), request_uri.end(), match_results, regex)) {
            return nullptr;
        }
        header._host = match_results[1];
        try {
            header._port = static_cast<unsigned short>(std::stoul(std::string(match_results[2])));
        }
        catch (const std::exception&) {
            return nullptr;
        }
    }
    else {
        boost::regex regex("(.+?)://(.+?)(:(\\d+))?(/.*)");
        boost::match_results<std::string::iterator> match_results;
        if (!boost::regex_match(request_uri.begin(), request_uri.end(), match_results, regex)) {
            return nullptr;
        }
        header._scheme = match_results[1];
        header._host = match_results[2];
        if (match_results[4].matched) {
            try {
                header._port = static_cast<unsigned short>(std::stoul(std::string(match_results[4])));
            }
            catch (const std::exception&) {
                return nullptr;
            }
        }
        header._path_and_query = match_results[5];
    }

    tmp = ++iter;
    for (;iter != end && *iter != '\r'; ++iter)
        ;
    // HTTP/x.y
    if (iter == end || std::distance(tmp, iter) < 6 || !std::equal(tmp, tmp + 5, "HTTP/")) return nullptr;

    header._http_version = std::string(tmp + 5, iter);

    ++iter;
    if (iter == end || *iter != '\n') return nullptr;

    ++iter;
    try {
        header._headers_map = parse_headers(iter, end);
    }
    catch (const std::exception&) {
        return nullptr;
    }

    return header;
}
Esempio n. 25
0
/* atomic "new_tran" construct; it returns:

	<0	on error

	+1	if a request did not match a transaction
		- it that was an ack, the calling function
		  shall forward statelessly
		- otherwise it means, a new transaction was
		  introduced and the calling function
		  shall reply/relay/whatever_appropriate

	0 on retransmission
*/
int t_newtran( struct sip_msg* p_msg )
{
	int lret, my_err;
	int canceled;


	/* is T still up-to-date ? */
	DBG("DEBUG: t_newtran: msg id=%d , global msg id=%d ,"
		" T on entrance=%p\n",p_msg->id,global_msg_id,T);

	if ( T && T!=T_UNDEFINED  ) {
		/* ERROR message moved to w_t_newtran */
		DBG("DEBUG: t_newtran: "
			"transaction already in process %p\n", T );
		return E_SCRIPT;
	}

	global_msg_id = p_msg->id;
	T = T_UNDEFINED;
	/* first of all, parse everything -- we will store in shared memory 
	   and need to have all headers ready for generating potential replies 
	   later; parsing later on demand is not an option since the request 
	   will be in shmem and applying parse_headers to it would intermix 
	   shmem with pkg_mem
	*/
	
	if (parse_headers(p_msg, HDR_EOH_F, 0 )) {
		LOG(L_ERR, "ERROR: t_newtran: parse_headers failed\n");
		return E_BAD_REQ;
	}
	if ((p_msg->parsed_flag & HDR_EOH_F)!=HDR_EOH_F) {
			LOG(L_ERR, "ERROR: t_newtran: EoH not parsed\n");
			return E_OUT_OF_MEM;
	}
	/* t_lookup_requests attempts to find the transaction; 
	   it also calls check_transaction_quadruple -> it is
	   safe to assume we have from/callid/cseq/to
	*/ 
	lret = t_lookup_request( p_msg, 1 /* leave locked if not found */,
								&canceled );

	/* on error, pass the error in the stack ... nothing is locked yet
	   if 0 is returned */
	if (lret==0) return E_BAD_TUPEL;

	/* transaction found, it's a retransmission  */
	if (lret>0) {
		if (p_msg->REQ_METHOD==METHOD_ACK) {
			t_release_transaction(T);
		} else {
			t_retransmit_reply(T);
		}
		/* things are done -- return from script */
		return 0;
	}

	/* from now on, be careful -- hash table is locked */

	if (lret==-2) { /* was it an e2e ACK ? if so, trigger a callback */
		/* no callbacks? complete quickly */
		if ( !has_tran_tmcbs(t_ack,TMCB_E2EACK_IN) ) {
			UNLOCK_HASH(p_msg->hash_index);
			return 1;
		} 
		REF_UNSAFE(t_ack);
		UNLOCK_HASH(p_msg->hash_index);
		/* we don't call from within REPLY_LOCK -- that introduces
		 * a race condition; however, it is so unlikely and the
		 * impact is so small (callback called multiple times of
		 * multiple ACK/200s received in parallel), that we do not
		 * better waste time in locks  */
		if (unmatched_totag(t_ack, p_msg)) {
			run_trans_callbacks( TMCB_E2EACK_IN , t_ack, p_msg, 0,
				-p_msg->REQ_METHOD );
		}
		UNREF(t_ack);
		return 1;
	} 


	/* transaction not found, it's a new request (lret<0, lret!=-2);
	   establish a new transaction ... */
	if (p_msg->REQ_METHOD==METHOD_ACK) { /* ... unless it is in ACK */
		my_err=1;
		goto new_err;
	}

	my_err=new_t(p_msg);
	if (my_err<0) {
		LOG(L_ERR, "ERROR: t_newtran: new_t failed\n");
		goto new_err;
	}
	if (canceled) T->flags|=T_CANCELED; /* mark it for future ref. */


	UNLOCK_HASH(p_msg->hash_index);
	/* now, when the transaction state exists, check if
 	   there is a meaningful Via and calculate it; better
 	   do it now than later: state is established so that
 	   subsequent retransmissions will be absorbed and will
  	  not possibly block during Via DNS resolution; doing
	   it later would only burn more CPU as if there is an
	   error, we cannot relay later whatever comes out of the
  	   the transaction 
	*/
	if (!init_rb( &T->uas.response, p_msg)) {
		LOG(L_ERR, "ERROR: t_newtran: unresolvable via1\n");
		put_on_wait( T );
		t_unref(p_msg);
		return E_BAD_VIA;
	}

	return 1;


new_err:
	UNLOCK_HASH(p_msg->hash_index);
	return my_err;

}
Esempio n. 26
0
int ac_cancel(as_p the_as,unsigned char processor_id,unsigned int flags,char *action,int len)
{
   unsigned int ret,cancelled_hashIdx,cancelled_label,i;
   struct sip_msg *my_msg;
   struct as_uac_param *the_param;
   struct cell* t_invite;
   int k,retval,uac_id;
   str headers,body;

   body.s=headers.s=NULL;
   my_msg=NULL;
   the_param=NULL;
   i=k=0;

   net2hostL(uac_id,action,k);

   net2hostL(cancelled_hashIdx,action,k);
   net2hostL(cancelled_label,action,k);

   if(!(headers.s=pkg_malloc(MAX_HEADER))){
      LM_ERR("Out of Memory!!");
      goto error;
   }
   headers.len=0;
   if(!(my_msg=pkg_malloc(sizeof(struct sip_msg)))){
      LM_ERR("out of memory!\n");
      goto error;
   }
   memset(my_msg,0,sizeof(struct sip_msg));
   my_msg->buf=action+k;
   my_msg->len=len-k;
   LM_DBG("Action UAC Message: uac_id:%d processor_id=%d, message:[%.*s]\n",
		   uac_id,processor_id,len-4,&action[4]);
   if(parse_msg(action+k,len-k,my_msg)<0){
      LM_ERR("parsing sip_msg");
      goto error;
   }
   if(my_msg->first_line.type==SIP_REPLY){
      LM_ERR("trying to create a UAC with a SIP response!!\n");
      goto error;
   }
   if(parse_headers(my_msg,HDR_EOH_F,0)==-1){
      LM_ERR("parsing headers\n");
      goto error;
   }
   if(0>(headers.len=extract_allowed_headers(my_msg,1,-1,HDR_CONTENTLENGTH_F|HDR_ROUTE_F|HDR_TO_F|HDR_FROM_F|HDR_CALLID_F|HDR_CSEQ_F,headers.s,MAX_HEADER))) {
      LM_ERR("Unable to extract allowed headers!!\n");
      goto error;
   }
   if(flags & SPIRAL_FLAG){
      memcpy(headers.s+headers.len,SPIRAL_HDR CRLF,SPIRAL_HDR_LEN + CRLF_LEN);
      headers.len+=SPIRAL_HDR_LEN+CRLF_LEN;
      /*headers.s[headers.len]=0;
      fake_uri.s=pkg_malloc(200);
      fake_uri.len=print_local_uri(the_as,processor_id,fake_uri.s,200);

      if(fake_uri.len<0){
	 SLM_ERR("printing local uri\n");
	 goto error;
      }
      my_dlg->hooks.next_hop=&fake_uri;*/
   }

   headers.s[headers.len]=0;

   /*let's get the body*/
   i=(unsigned int)get_content_length(my_msg);
   if(i!=0){
      if(!(body.s=pkg_malloc(i))){
	 LM_ERR("Out of Memory!");
	 goto error;
      }
      memcpy(body.s,get_body(my_msg),i);
      body.len=i;
      LM_DBG("Trying to construct a Sip Request with: body:%d[%s]"
			  " headers:%d[%s]\n", body.len,body.s,headers.len,headers.s);
   }else{
      body.s=NULL;
      body.len=0;
   }

   if(!(the_param=shm_malloc(sizeof(struct as_uac_param)))){
      LM_ERR("no more share memory\n");
      goto error;
   }

	if(seas_f.tmb.t_lookup_ident(&t_invite,cancelled_hashIdx,cancelled_label)<0){
		LM_ERR("failed to t_lookup_ident hash_idx=%d,"
			"label=%d\n", cancelled_hashIdx,cancelled_label);
		goto error;
	}
	seas_f.tmb.unref_cell(t_invite);

   the_param->who=my_as;
   the_param->uac_id=uac_id;
   the_param->processor_id=processor_id;
   the_param->destroy_cb_set=0;
   
   /* registers TMCB_RESPONSE_IN|TMCB_LOCAL_COMPLETED tm callbacks */
   ret=seas_f.tmb.t_cancel_uac(&headers,&body,cancelled_hashIdx,cancelled_label,uac_cb,(void*)the_param);
   if (ret == 0) {
      LM_ERR( "t_cancel_uac failed\n");
      as_action_fail_resp(uac_id,SE_CANCEL,SE_CANCEL_MSG,SE_CANCEL_MSG_LEN);
      goto error;
   }else{
      the_param->label=ret;
   }

	seas_f.tmb.unref_cell(t_invite);
   retval=0;
   goto exit;
error:
   retval = -1;
   if(the_param)
      shm_free(the_param);
exit:
   if(headers.s)
      pkg_free(headers.s);
   if(body.s)
      pkg_free(body.s);
   if(my_msg){
      if(my_msg->headers)
	 free_hdr_field_lst(my_msg->headers);
      pkg_free(my_msg);
   }
   return retval;
}
Esempio n. 27
0
/* Determine current transaction
 *
 *                   Found      Not Found     Error (e.g. parsing)
 *  Return Value     1          0             -1
 *  T                ptr        0             T_UNDEFINED
 */
int t_check( struct sip_msg* p_msg , int *param_branch )
{
	int local_branch;
	int canceled;

	/* is T still up-to-date ? */
	DBG("DEBUG: t_check: msg id=%d global id=%d T start=%p\n", 
		p_msg->id,global_msg_id,T);
	if ( p_msg->id != global_msg_id || T==T_UNDEFINED )
	{
		global_msg_id = p_msg->id;
		T = T_UNDEFINED;
		/* transaction lookup */
		if ( p_msg->first_line.type==SIP_REQUEST ) {
			/* force parsing all the needed headers*/
			if (parse_headers(p_msg, HDR_EOH_F, 0 )==-1) {
				LOG(L_ERR, "ERROR: t_check: parsing error\n");
				return -1;
			}
			/* in case, we act as UAS for INVITE and reply with 200,
			 * we will need to run dialog-matching for subsequent
			 * ACK, for which we need From-tag; We also need from-tag
			 * in case people want to have proxied e2e ACKs accounted
			 */
			if (p_msg->REQ_METHOD==METHOD_INVITE 
							&& parse_from_header(p_msg)==-1) {
				LOG(L_ERR, "ERROR: t_check: from parsing failed\n");
				return -1;
			}
			t_lookup_request( p_msg , 0 /* unlock before returning */,
								&canceled);
		} else {
			/* we need Via for branch and Cseq method to distinguish
			   replies with the same branch/cseqNr (CANCEL)
			   and we need all the WWW/Proxy Authenticate headers for
			   401 & 407 replies
			*/
			if (tm_aggregate_auth && 
					(p_msg->REPLY_STATUS==401 || p_msg->REPLY_STATUS==407)){
				if (parse_headers(p_msg, HDR_EOH_F,0)==-1){
					LOG(L_WARN, "WARNING: the reply cannot be "
								"completely parsed\n");
					/* try to continue, via1 & cseq are checked below */
				}
			}else if ( parse_headers(p_msg, HDR_VIA1_F|HDR_CSEQ_F, 0 )==-1) {
				LOG(L_ERR, "ERROR: reply cannot be parsed\n");
				return -1;
			}
			if ((p_msg->via1==0) || (p_msg->cseq==0)){
				LOG(L_ERR, "ERROR: reply doesn't have a via or cseq header\n");
				return -1;
			}
			/* if that is an INVITE, we will also need to-tag
			   for later ACK matching
			*/
            if ( get_cseq(p_msg)->method.len==INVITE_LEN 
				&& memcmp( get_cseq(p_msg)->method.s, INVITE, INVITE_LEN )==0 ) {
					if (parse_headers(p_msg, HDR_TO_F, 0)==-1
						|| !p_msg->to)  {
						LOG(L_ERR, "ERROR: INVITE reply cannot be parsed\n");
						return -1;
					}
			}

			t_reply_matching( p_msg ,
				param_branch!=0?param_branch:&local_branch );

		}
#ifdef EXTRA_DEBUG
		if ( T && T!=T_UNDEFINED && T->flags & (T_IN_AGONY)) {
			LOG( L_ERR, "ERROR: transaction %p scheduled for deletion "
				"and called from t_check (flags=%x)\n", T, T->flags);
			abort();
		}
#endif
		DBG("DEBUG: t_check: msg id=%d global id=%d T end=%p\n",
			p_msg->id,global_msg_id,T);
	} else {
		if (T)
			DBG("DEBUG: t_check: T already found!\n");
		else
			DBG("DEBUG: t_check: T previously sought and not found\n");
	}

	return T ? (T==T_UNDEFINED ? -1 : 1 ) : 0;
}
Esempio n. 28
0
/*Actions are composed as follows:
 * (the action length and type as always= 5 bytes)
 * 4:uac_id
 *
 * int request(str* method, str* req_uri, str* to, str* from, str* headers, str* body, transaction_cb c, void* cp)
 * TODO performance speedup: instead of using
 * dynamically allocated memory for headers,body,totag,reason and my_msg
 * use static buffers.
 *
 */
int ac_uac_req(as_p the_as,unsigned char processor_id,unsigned int flags,char *action,int len)
{
   unsigned int cseq;
   char err_buf[MAX_REASON_LEN];
   struct sip_msg *my_msg;
   struct to_body *fb,*tb;
   struct cseq_body *cseqb;
   struct as_uac_param *the_param;
   dlg_t *my_dlg;
   int k,retval,uac_id,sip_error,ret,err_ret;
   long clen;
   str headers,body,fake_uri;
   uac_req_t uac_r;

   headers.s=body.s=fake_uri.s=NULL;
   my_dlg=NULL;
   my_msg=NULL;
   the_param=NULL;
   k=clen=0;

   net2hostL(uac_id,action,k);

   if(!(headers.s=pkg_malloc(MAX_HEADER))){
      LM_ERR("Out of Memory!!");
      goto error;
   }
   headers.len=0;
   LM_DBG("Action UAC Message: uac_id:%d processor_id=%d\n",uac_id,processor_id);
   if (!(my_msg = parse_ac_msg(HDR_EOH_F,action+k,len-k))) {
      LM_ERR("out of memory!\n");
      goto error;
   }
   if(my_msg->first_line.type==SIP_REPLY){
      LM_ERR("trying to create a UAC with a SIP response!!\n");
      goto error;
   }
   if(parse_headers(my_msg,HDR_EOH_F,0)==-1){
      LM_ERR("ERROR:seas:ac_uac_req:parsing headers\n");
      goto error;
   }
   if(parse_from_header(my_msg)<0){
      LM_ERR("parsing from header ! \n");
      goto error;
   }
   if(check_transaction_quadruple(my_msg)==0){
      as_action_fail_resp(uac_id,SE_UAC,"Headers missing (to,from,call-id,cseq)?",0);
      LM_ERR("Headers missing (to,from,call-id,cseq)?");
      goto error;
   }
   if(!(get_from(my_msg)) || !(get_from(my_msg)->tag_value.s) || 
	 !(get_from(my_msg)->tag_value.len)){
      as_action_fail_resp(uac_id,SE_UAC,"From tag missing",0);
      LM_ERR("From tag missing");
      goto error;
   }
   fb=my_msg->from->parsed;
   tb=my_msg->to->parsed;
   cseqb=my_msg->cseq->parsed;
   if(0!=(str2int(&cseqb->number,&cseq))){
      LM_DBG("unable to parse CSeq\n");
      goto error;
   }
   if(my_msg->first_line.u.request.method_value != METHOD_ACK &&
	 my_msg->first_line.u.request.method_value != METHOD_CANCEL) {
      /** we trick req_within */
      cseq--;
   }
   if(seas_f.tmb.new_dlg_uac(&(my_msg->callid->body),&(fb->tag_value),cseq,\
	    &(fb->uri),&(tb->uri),&my_dlg) < 0) {
      as_action_fail_resp(uac_id,SE_UAC,"Error creating new dialog",0);
      LM_ERR("Error while creating new dialog\n");
      goto error;
   }
   if(seas_f.tmb.dlg_add_extra(my_dlg,&(fb->display),&(tb->display)) < 0 ) {
      as_action_fail_resp(uac_id,SE_UAC,
         "Error adding the display names to the new dialog",0);
      LM_ERR("failed to add display names to the new dialog\n");
      goto error;
   }

   if(tb->tag_value.s && tb->tag_value.len)
      shm_str_dup(&my_dlg->id.rem_tag,&tb->tag_value);
   /**Awful hack: to be able to set our own CSeq, from_tag and call-ID we have
    * to use req_within instead of req_outside (it sets it's own CSeq,Call-ID
    * and ftag), so we have to simulate that the dialog is already in completed
    * state so...
    */
   server_signature=0;
   my_dlg->state = DLG_CONFIRMED;
   if(0>(headers.len=extract_allowed_headers(my_msg,1,-1,HDR_CONTENTLENGTH_F|HDR_ROUTE_F|HDR_TO_F|HDR_FROM_F|HDR_CALLID_F|HDR_CSEQ_F,headers.s,MAX_HEADER))) {
      LM_ERR("Unable to extract allowed headers!!\n");
      goto error;
   }
   headers.s[headers.len]=0;
   /*let's get the body*/
   if(my_msg->content_length)
      clen=(long)get_content_length(my_msg);
   if(clen!=0){
      if(!(body.s=pkg_malloc(clen))){
	 LM_ERR("Out of Memory!");
	 goto error;
      }
      memcpy(body.s,get_body(my_msg),clen);
      body.len=clen;
      body.s[clen]=0;
      LM_DBG("Trying to construct a Sip Request with: body:%d[%.*s] headers:%d[%.*s]\n",\
	    body.len,body.len,body.s,headers.len,headers.len,headers.s);
      /*t_reply_with_body un-ref-counts the transaction, so dont use it anymore*/
   }else{
      body.s=NULL;
      body.len=0;
   }
   /*Now... create the UAC !!
    * it would be great to know the hash_index and the label that have been assigned
    * to our newly created cell, but t_uac does not leave any way for us to know...
    * only that when that transaction transitions its state (ie. a response is received,
    * a timeout is reached, etc...) the callback will be called with the given parameter.
    *
    * So the only way we have to know who we are, is passing as a parameter a structure with
    * 2 pointers: one to the app_server and the other, the identifier of the UAC (uac_id).
    *
    */
   if(!(the_param=shm_malloc(sizeof(struct as_uac_param)))){
      LM_ERR("out of shared memory\n");
      goto error;
   }
   the_param->who=my_as;
   the_param->uac_id=uac_id;
   the_param->processor_id=processor_id;
   the_param->destroy_cb_set=0;

   shm_str_dup(&my_dlg->rem_target,&my_msg->first_line.u.request.uri);

   if (my_msg->route) {
      if (parse_rr(my_msg->route) < 0) {
	 LM_ERR( "Error while parsing Route body\n");
	 goto error;
      }
      /* TODO route_set should be a shm copy of my_msg->route->parsed */
      my_dlg->route_set=(rr_t*)my_msg->route->parsed;
      /** this SHOULD be:
       shm_duplicate_rr(&my_dlg->route_set,my_msg->route->parsed);
       * but it will last more...
       */
   }
   calculate_hooks(my_dlg);
   if(flags & SPIRAL_FLAG){
      memcpy(headers.s+headers.len,SPIRAL_HDR CRLF,SPIRAL_HDR_LEN + CRLF_LEN);
      headers.len+=SPIRAL_HDR_LEN+CRLF_LEN;
      headers.s[headers.len]=0;
      fake_uri.s=pkg_malloc(200);
      fake_uri.len=print_local_uri(the_as,processor_id,fake_uri.s,200);

      if(fake_uri.len<0){
	 LM_ERR("printing local uri\n");
	 goto error;
      }
      my_dlg->hooks.next_hop=&fake_uri;
   }
   /* Kamailio and OpenSIPs seem to have diverged quite a bit on flags and events
      notified to UACs. Let's see if kamailio gets it right by now, if not
      this is a TODO: check PASS_PROVISIONAL
      my_dlg->T_flags=T_NO_AUTO_ACK|T_PASS_PROVISIONAL_FLAG ;
      this is the same as (TMCB_DONT_ACK|TMCB_LOCAL_RESPONSE_OUT) in Kamailio
   */

   set_uac_req(&uac_r, &(my_msg->first_line.u.request.method), &headers,
		   &body, my_dlg,TMCB_DONT_ACK|TMCB_LOCAL_RESPONSE_OUT, uac_cb,
		   (void*)the_param);

   ret=seas_f.tmb.t_request_within(&uac_r);

   /** now undo all the fakes we have put in my_dlg*/
   /*because my_dlg->route_set should be shm but we fake it (its pkg_mem)*/
   my_dlg->route_set=(rr_t *)0;
   if (ret < 0) {
      err_ret = err2reason_phrase(ret,&sip_error,err_buf, sizeof(err_buf), "SEAS/UAC");
      LM_ERR("failed to send the [%.*s] request\n",uac_r.method->len,uac_r.method->s);
      LM_ERR("Error on request_within %s\n",err_buf );
      if(err_ret > 0) {
	 as_action_fail_resp(uac_id,ret,err_buf,0);
      }else{
	 as_action_fail_resp(uac_id,E_UNSPEC,"500 SEAS/UAC error",0);
      }
      goto error;
   }
   retval=0;
   goto exit;
error:
   retval = -1;
   if(the_param)
      shm_free(the_param);
exit:
   seas_f.tmb.free_dlg(my_dlg);
   if(headers.s)
      pkg_free(headers.s);
   if(body.s)
      pkg_free(body.s);
   if(fake_uri.s)
      pkg_free(fake_uri.s);
   if(my_msg){
      if(my_msg->headers)
	 free_hdr_field_lst(my_msg->headers);
      pkg_free(my_msg);
   }
   return retval;
}
Esempio n. 29
0
/*
 * determines the permission of the call
 * return values:
 * -1:	deny
 * 1:	allow
 */
static int check_routing(struct sip_msg* msg, int idx)
{
	struct hdr_field *from;
	int len, q;
	static char from_str[EXPRESSION_LENGTH+1];
	static char ruri_str[EXPRESSION_LENGTH+1];
	char* uri_str;
	str branch;
	int br_idx;

	/* turn off control, allow any routing */
	if ((!allow[idx].rules) && (!deny[idx].rules)) {
		LM_DBG("no rules => allow any routing\n");
		return 1;
	}

	/* looking for FROM HF */
	if ((!msg->from) && (parse_headers(msg, HDR_FROM_F, 0) == -1)) {
		LM_ERR("failed to parse message\n");
		return -1;
	}

	if (!msg->from) {
		LM_ERR("FROM header field not found\n");
		return -1;
	}

	/* we must call parse_from_header explicitly */
	if ((!(msg->from)->parsed) && (parse_from_header(msg) < 0)) {
		LM_ERR("failed to parse From body\n");
		return -1;
	}

	from = msg->from;
	len = ((struct to_body*)from->parsed)->uri.len;
	if (len > EXPRESSION_LENGTH) {
		LM_ERR("From header field is too long: %d chars\n", len);
		return -1;
	}
	strncpy(from_str, ((struct to_body*)from->parsed)->uri.s, len);
	from_str[len] = '\0';

	/* looking for request URI */
	if (parse_sip_msg_uri(msg) < 0) {
		LM_ERR("uri parsing failed\n");
		return -1;
	}

	len = msg->parsed_uri.user.len + msg->parsed_uri.host.len + 5;
	if (len > EXPRESSION_LENGTH) {
		LM_ERR("Request URI is too long: %d chars\n", len);
		return -1;
	}

	strcpy(ruri_str, "sip:");
	memcpy(ruri_str + 4, msg->parsed_uri.user.s, msg->parsed_uri.user.len);
	ruri_str[msg->parsed_uri.user.len + 4] = '@';
	memcpy(ruri_str + msg->parsed_uri.user.len + 5, msg->parsed_uri.host.s, msg->parsed_uri.host.len);
	ruri_str[len] = '\0';

	LM_DBG("looking for From: %s Request-URI: %s\n", from_str, ruri_str);
	/* rule exists in allow file */
	if (search_rule(allow[idx].rules, from_str, ruri_str)) {
		if (check_all_branches) goto check_branches;
		LM_DBG("allow rule found => routing is allowed\n");
		return 1;
	}

	/* rule exists in deny file */
	if (search_rule(deny[idx].rules, from_str, ruri_str)) {
		LM_DBG("deny rule found => routing is denied\n");
		return -1;
	}

	if (!check_all_branches) {
		LM_DBG("neither allow nor deny rule found => routing is allowed\n");
		return 1;
	}

check_branches:
	for( br_idx=0 ; (branch.s=get_branch(br_idx,&branch.len,&q,0,0,0,0,0,0,0))!=0 ;
			br_idx++ ) {
		uri_str = get_plain_uri(&branch);
		if (!uri_str) {
			LM_ERR("failed to extract plain URI\n");
			return -1;
		}
		LM_DBG("looking for From: %s Branch: %s\n", from_str, uri_str);

		if (search_rule(allow[idx].rules, from_str, uri_str)) {
			continue;
		}

		if (search_rule(deny[idx].rules, from_str, uri_str)) {
			LM_DBG("deny rule found for one of branches => routing"
					"is denied\n");
			return -1;
		}
	}

	LM_DBG("check of branches passed => routing is allowed\n");
	return 1;
}
Esempio n. 30
0
/**
 * Updates dialog on reply message
 * @param msg - the SIP message 
 * @param d - dialog to modify
 * @returns 1 on success or 0 on error
 */
int update_dialog_on_reply(struct sip_msg *msg, s_dialog *d)
{
	struct hdr_field *h_req;
	struct hdr_field *h=0;
	int res=0;
	time_t t_time=0;
	str ses_exp = {0,0};
	str refresher = {0,0};
	str new_ses_exp = {0,0};
	str new_ext = {0,0};

	ses_exp = cscf_get_session_expires_body(msg, &h);
	t_time = cscf_get_session_expires(ses_exp, &refresher);
	if (!t_time) //i.e not session-expires header in response
	{
		if (!d->uac_supp_timer || !d->lr_session_expires)
		{
			d->expires = d_act_time()+scscf_dialogs_expiration_time;	
		}
		else// uac supports timer, but no session-expires header found in response
		{
			new_ses_exp.len = 11/*int value*/ + str_se.len+s_refresher.len+8;
			new_ses_exp.s = pkg_malloc(new_ses_exp.len+1);
			if (!new_ses_exp.s) {
				LOG(L_ERR,"ERR:"M_NAME":update_dialog_on_reply: Error allocating %d bytes\n",new_ses_exp.len);
				goto error;
			}
			new_ses_exp.len = snprintf(new_ses_exp.s, new_ses_exp.len, "%.*s %d; %.*suac\r\n",str_se.len, str_se.s, (int)d->lr_session_expires ,s_refresher.len, s_refresher.s);
			cscf_add_header(msg, &new_ses_exp, HDR_OTHER_T);
			if (!requires_extension(msg, &str_ext_timer)) //must have require timer extenstion
			{
				/* walk through all Require headers to find first require header*/
				res = parse_headers(msg, HDR_EOH_F, 0);
				if (res == -1) {
					ERR("Error while parsing headers (%d)\n", res);
					return 0; /* what to return here ? */
				}
				
				h_req = msg->require;
				while (h_req) {
					if (h_req->type == HDR_REQUIRE_T) {
						if (h_req->body.s[new_ext.len-1]=='\n')
						{
							new_ext.len = str_require.len + 1/* */+h_req->body.len + 7;/*, timer*/
							new_ext.s = pkg_malloc(new_ext.len);
							if (!new_ext.s) {
								LOG(L_ERR,"ERR:"M_NAME":update_dialog_on_reply: Error allocating %d bytes\n",new_ext.len);
								goto error;
							}			
							new_ext.len = snprintf(new_ext.s, str_require.len, "%.*s %.*s, timer\r\n", str_require.len, str_require.s, h_req->body.len-2, h_req->body.s);
						}
						else
						{
							new_ext.len = str_require.len + 1/*space*/ + h_req->body.len + 9;/*, timer\r\n*/
							new_ext.s = pkg_malloc(new_ext.len);
							if (!new_ext.s) {
								LOG(L_ERR,"ERR:"M_NAME":update_dialog_on_reply: Error allocating %d bytes\n",new_ext.len);
								goto error;
							}			
							new_ext.len = snprintf(new_ext.s, str_require.len, "%.*s %.*s, timer\r\n", str_require.len, str_require.s, h_req->body.len, h_req->body.s);
						}
						cscf_del_header(msg, h_req);
						cscf_add_header(msg, &new_ext, HDR_REQUIRE_T);
						break;
					}
					h_req = h_req->next;
				}
			}
		}
	}
	return 1;
error:
	if (new_ses_exp.s) pkg_free(new_ses_exp.s);
	if (new_ext.s) pkg_free(new_ext.s);
	return 0;	
}