Example #1
0
int dlg_th_decode_callid(struct sip_msg *msg)
{
	struct lump *del;
	str new_callid;
	int i,max_size;

	if (msg->callid == NULL) {
		LM_ERR("Message with no callid\n");
		return -1;
	}

	max_size = calc_max_base64_decode_len(msg->callid->body.len - topo_hiding_prefix.len);
	new_callid.s = pkg_malloc(max_size);
	if (new_callid.s==NULL) {
		LM_ERR("No more pkg\n");
		return -1;
	}
		
	new_callid.len = base64decode((unsigned char *)(new_callid.s),
			(unsigned char *)(msg->callid->body.s + topo_hiding_prefix.len),
			msg->callid->body.len - topo_hiding_prefix.len);
	for (i=0;i<new_callid.len;i++)
		new_callid.s[i] ^= topo_hiding_seed.s[i%topo_hiding_seed.len]; 

	del=del_lump(msg, msg->callid->body.s-msg->buf, msg->callid->body.len, HDR_CALLID_T);
	if (del==NULL) {               
		LM_ERR("Failed to delete old callid\n");
		pkg_free(new_callid.s);
		return -1;
	}

	if (insert_new_lump_after(del,new_callid.s,new_callid.len,HDR_CALLID_T)==NULL) {
		LM_ERR("Failed to insert new callid\n");
		pkg_free(new_callid.s);
		return -1;
	}

	return 0;

	return 0;
}
Example #2
0
/*
 * Logic necessary to forward request to strict routers
 *
 * Returns 0 on success, negative number on an error
 */
static inline int handle_sr(struct sip_msg* _m, struct hdr_field* _hdr, rr_t* _r)
{
	str uri;
	char* rem_off;
	int rem_len;

	/* Next hop is strict router, save R-URI here */
	if (save_ruri(_m) < 0) {
		LM_ERR("failed to save Request-URI\n");
		return -1;
	}

	/* Put the first Route in Request-URI */

	uri = _r->nameaddr.uri;
	if(get_maddr_uri(&uri, 0)!=0) {
		LM_ERR("failed to check maddr\n");
		return RR_ERROR;
	}
	if (set_ruri(_m, &uri) < 0) {
		LM_ERR("failed to rewrite request URI\n");
		return -2;
	}

	if (!_r->next) {
		rem_off = _hdr->name.s;
		rem_len = _hdr->len;
	} else {
		rem_off = _hdr->body.s;
		rem_len = _r->next->nameaddr.name.s - _hdr->body.s;
	}

	if (!del_lump(_m, rem_off - _m->buf, rem_len, 0)) {
		LM_ERR("failed to remove Route HF\n");
		return -9;
	}

	_r->deleted = 1;

	return 0;
}
Example #3
0
static int replace_body_f(struct sip_msg* msg, char* key, char* str2)
{
	struct lump* l;
	regmatch_t pmatch;
	char* s;
	int len;
	char* begin;
	int off;
	str body;

	if ( get_body(msg,&body)!=0 || body.len==0) {
		LM_DBG("message body has zero length\n");
		return -1;
	}

	begin=body.s; /* msg->orig previously .. uri problems */

	if (regexec((regex_t*) key, begin, 1, &pmatch, 0)!=0) return -1;
	off=begin-msg->buf;

	if (pmatch.rm_so!=-1){
		if ((l=del_lump(msg, pmatch.rm_so+off,
						pmatch.rm_eo-pmatch.rm_so, 0))==0)
			return -1;
		len=strlen(str2);
		s=pkg_malloc(len);
		if (s==0){
			LM_ERR("memory allocation failure\n");
			return -1;
		}
		memcpy(s, str2, len);
		if (insert_new_lump_after(l, s, len, 0)==0){
			LM_ERR("could not insert new lump\n");
			pkg_free(s);
			return -1;
		}

		return 1;
	}
	return -1;
}
Example #4
0
/* sed-perl style re: s/regular expression/replacement/flags */
static int subst_f(struct sip_msg* msg, char*  subst, char* ignored)
{
	struct lump* l;
	struct replace_lst* lst;
	struct replace_lst* rpl;
	char* begin;
	struct subst_expr* se;
	int off;
	int ret;
	
	se=(struct subst_expr*)subst;
	begin=get_header(msg);  /* start after first line to avoid replacing
							   the uri */
	off=begin-msg->buf;
	ret=-1;
	if ((lst=subst_run(se, begin, msg))==0) goto error; /* not found */
	for (rpl=lst; rpl; rpl=rpl->next){
		DBG(" %s: subst_f: replacing at offset %d [%.*s] with [%.*s]\n",
				exports.name, rpl->offset+off,
				rpl->size, rpl->offset+off+msg->buf,
				rpl->rpl.len, rpl->rpl.s);
		if ((l=del_lump(msg, rpl->offset+off, rpl->size, 0))==0)
			goto error;
		/* hack to avoid re-copying rpl, possible because both 
		 * replace_lst & lumps use pkg_malloc */
		if (insert_new_lump_after(l, rpl->rpl.s, rpl->rpl.len, 0)==0){
			LOG(L_ERR, "ERROR: %s: subst_f: could not insert new lump\n",
					exports.name);
			goto error;
		}
		/* hack continued: set rpl.s to 0 so that replace_lst_free will
		 * not free it */
		rpl->rpl.s=0;
		rpl->rpl.len=0;
	}
	ret=1;
error:
	DBG("subst_f: lst was %p\n", lst);
	if (lst) replace_lst_free(lst);
	return ret;
}
Example #5
0
int tps_remove_name_headers(sip_msg_t *msg, str *hname)
{
	hdr_field_t *hf;
	struct lump* l;
	for (hf=msg->headers; hf; hf=hf->next)
	{
		if (hf->name.len==hname->len
				&& strncasecmp(hf->name.s, hname->s,
					hname->len)==0)
		{
			l=del_lump(msg, hf->name.s-msg->buf, hf->len, 0);
			if (l==0) {
				LM_ERR("unable to delete header [%.*s]\n",
						hname->len, hname->s);
				return -1;
			}
			return 0;
		}
	}
	return 0;
}
Example #6
0
/**
 * Remove a header from a message if found.
 *
 * @param msg The message to look for the header to remove.
 * @param header The header name: text.
 *
 * @return 0 if the header was not found, >0 is successful, -1 on an
 *         error.
 */
static int remove_minse_header(struct sip_msg *msg)
{
	struct lump* anchor = NULL;
	struct hdr_field *hf = NULL;
	int cnt = 0;

	/* parse all headers as we want to get all MIN-SE headers*/
	if (parse_headers(msg, HDR_EOH_F, 0) == -1) {
		LM_ERR("failed to parse headers in message.\n");
		return(-1);
	}

	for (hf = msg->min_se; hf; hf = hf->sibling) {
		anchor = del_lump(msg, hf->name.s-msg->buf, hf->len, 0);
		if (anchor == 0) {
			LM_ERR("no more pkg memory\n");
			return -1;
		}
		cnt++;
	}
	return cnt;
}
Example #7
0
int gzc_set_msg_body(sip_msg_t *msg, str *obody, str *nbody)
{
	struct lump *anchor;
	char* buf;

	/* none should be here - just for safety */
	del_nonshm_lump( &(msg->body_lumps) );
	msg->body_lumps = NULL;

	if(del_lump(msg, obody->s - msg->buf, obody->len, 0) == 0)
	{
		LM_ERR("cannot delete existing body");
		return -1;
	}

	anchor = anchor_lump(msg, obody->s - msg->buf, 0, 0);

	if (anchor == 0)
	{
		LM_ERR("failed to get body anchor\n");
		return -1;
	} 

	buf=pkg_malloc(nbody->len * sizeof(char));
	if (buf==0)
	{
		LM_ERR("out of pkg memory\n");
		return -1;
	}
	memcpy(buf, nbody->s, nbody->len);
	if (insert_new_lump_after(anchor, buf, nbody->len, 0) == 0)
	{
		LM_ERR("failed to insert body lump\n");
		pkg_free(buf);
		return -1;
	}
	return 0;
}
Example #8
0
static int remove_hf_f(struct sip_msg* msg, char* str_hf, char* foo)
{
	struct hdr_field *hf;
	struct lump* l;
	int cnt;

	cnt=0;
	/* we need to be sure we have seen all HFs */
	parse_headers(msg, HDR_EOH, 0);
	for (hf=msg->headers; hf; hf=hf->next) {
		if (hf->name.len!=((str *)str_hf)->len)
			continue;
		if (strncasecmp(hf->name.s, ((str *)str_hf)->s, hf->name.len)!=0)
			continue;
		l=del_lump(msg, hf->name.s-msg->buf, hf->len, 0);
		if (l==0) {
			LOG(L_ERR, "ERROR: remove_hf_f: no memory\n");
			return -1;
		}
		cnt++;
	}
	return cnt==0 ? -1 : 1;
}
Example #9
0
static int lua_sr_hdr_remove (lua_State *L)
{
	struct lump* anchor;
	struct hdr_field *hf;
	char *txt;
	str hname;
	sr_lua_env_t *env_L;

	env_L = sr_lua_env_get();

	txt = (char*)lua_tostring(L, -1);
	if(txt==NULL || env_L->msg==NULL)
		return 0;

	LM_DBG("remove hf: %s\n", txt);
	if (parse_headers(env_L->msg, HDR_EOH_F, 0) == -1) {
		LM_ERR("error while parsing message\n");
		return 0;
	}

	hname.s = txt;
	hname.len = strlen(txt);
	for (hf=env_L->msg->headers; hf; hf=hf->next)
	{
		if (cmp_hdrname_str(&hf->name, &hname)==0)
		{
			anchor=del_lump(env_L->msg,
					hf->name.s - env_L->msg->buf, hf->len, 0);
			if (anchor==0)
			{
				LM_ERR("cannot remove hdr %s\n", txt);
				return 0;
			}
		}
	}
	return 0;
}
Example #10
0
int th_unmask_callid(sip_msg_t *msg)
{
	struct lump* l;
	str out;
	
	if(th_param_mask_callid==0)
		return 0;
	
	if(msg->callid==NULL)
	{
		LM_ERR("cannot get Call-Id header\n");
		return -1;
	}
				
	out.s = th_mask_decode(msg->callid->body.s, msg->callid->body.len,
					&th_callid_prefix, 0, &out.len);
	if(out.s==NULL)
	{
		LM_ERR("cannot decode callid\n");
		return -1;
	}
				
	l=del_lump(msg, msg->callid->body.s-msg->buf, msg->callid->body.len, 0);
	if (l==0)
	{
		LM_ERR("failed deleting callid\n");
		pkg_free(out.s);
		return -1;
	}
	if (insert_new_lump_after(l, out.s, out.len, 0)==0) {
		LM_ERR("could not insert new lump\n");
		pkg_free(out.s);
		return -1;
	}

	return 0;
}
Example #11
0
static int w_remove_body_f(struct sip_msg *msg, char *p1, char *p2)
{
	str body = {0,0};

	body.len = 0;
	body.s = get_body(msg);
	if (body.s==0)
	{
		LM_DBG("no body in the message\n");
		return 1;
	}
	body.len = msg->buf + msg->len - body.s;
	if (body.len<=0)
	{
		LM_DBG("empty body in the message\n");
		return 1;
	}
	if(del_lump(msg, body.s - msg->buf, body.len, 0) == 0)
	{
		LM_ERR("cannot remove body\n");
		return -1;
	}
	return 1;
}
Example #12
0
int replace_body_segment(struct sdp_mangler * mangler, int offset, int len, unsigned char * new_data, int new_len)
{
	
	struct lump * l;
	char *s;

	l = del_lump(mangler->msg, mangler->body_offset + offset, len, 0);

	if(l == NULL)
	{
		return -1;
	}

 	s = pkg_malloc(new_len);
	memcpy(s, new_data, new_len);

	if(insert_new_lump_after(l, s, new_len, 0) == 0)
	{
		pkg_free(s);
		return -2;
	}

	return 0;
}
Example #13
0
/**
 * remove_sdp_stream_attrs - removes all attributes from the specified stream
 *
 * @return: struct lump * with the removed information
 */
static struct lump *remove_sdp_stream_attrs(struct sip_msg *msg,
                                      struct sdp_stream_cell *stream)
{
	struct lump *lump;
	char *attrs_end = NULL;

	LM_DBG("Removing all %d codecs from SDP stream: |%.*s|\n",
	       stream->payloads_num, stream->payloads.len, stream->payloads.s);

	/* find the last parsed structure of the last attribute */
	if (stream->payload_attr->fmtp_string.len > 0) {
		attrs_end = stream->payload_attr->fmtp_string.s +
		          stream->payload_attr->fmtp_string.len;
	} else if (stream->payload_attr->rtp_params.len > 0) {
		attrs_end = stream->payload_attr->rtp_params.s +
		          stream->payload_attr->rtp_params.len;
	} else if (stream->payload_attr->rtp_clock.len > 0) {
		attrs_end = stream->payload_attr->rtp_clock.s +
		          stream->payload_attr->rtp_clock.len;
	}

	if (!attrs_end) {
		LM_ERR("invalid SDP stream received\n");
		print_sdp_stream(stream, L_ERR);
		return NULL;
	}

	lump = del_lump(msg, stream->payloads.s - msg->buf,
	                attrs_end - stream->payloads.s, HDR_OTHER_T);
	if (!lump) {
		LM_ERR("failed to add del lump\n");
		return NULL;
	}

	return lump;
}
Example #14
0
/**
 * Send the request back simulating an AS. 
 * - Inserts a Header with the contents of str2
 * - Tries to find the Route: appserver_uri, s-cscf_uri header and removes appserver_uri from it
 * - It forwards the message to s-scsf_uri, or if none found to str1
 *	@param msg - The sip message
 *	@param str1 - The uri of the SCSCF to default to if Route header is not found
 *	@param str2 - The Header to add to the message - if empty none will be added
 *	@returns	- 0 to cancel further script processing 
 */
int isc_appserver_forward(struct sip_msg *msg,char *str1,char *str2 )
{
	struct hdr_field *last,*hdr;
	struct lump* anchor;
	str header_mark;
	rr_t *rr;

	LOG(L_DBG,"DEBUG:"M_NAME":isc_appserver_forward: Forward-back request reached\n");
	parse_headers(msg,HDR_EOH_F,0);
	last = msg->headers;
	while(last->next)
		last = last->next;

	LOG(L_INFO,"INFO:"M_NAME":isc_appserver_forward: New header: [%s]\n%.*s",str2,msg->len,msg->buf);
	
    /* Put header marking */

	if (strlen(str2)){
	
		header_mark.s = pkg_malloc(256);//36 should be enough
		sprintf(header_mark.s,"%.*s\n",strlen(str2),str2);
		header_mark.len =strlen(header_mark.s);
	
		anchor = anchor_lump(msg, last->name.s + last->len - msg->buf, 0 , 0);
		if (anchor == NULL) {
				LOG(L_ERR, "ERROR:"M_NAME":isc_appserver_forward: anchor_lump failed\n");
		}
	
		if (!insert_new_lump_before(anchor, header_mark.s,header_mark.len,0)){
				LOG( L_ERR, "ERROR:"M_NAME":isc_appserver_forward: error creting lump for header_mark\n" );
		}
		//pkg_free(header_mark.s);
	}
	LOG(L_ERR, "INFO:"M_NAME":isc_appserver_forward: Searching Route header to rewrite\n");
	/* Search for the Route */
	hdr = msg->headers;
	while(hdr){
		if (hdr->type == HDR_ROUTE_T){
			if (!hdr->parsed){
				if (parse_rr(hdr) < 0) {
					LOG(L_ERR, "ERROR:"M_NAME":isc_appserver_forward: Error while parsing Route HF\n");
					continue;
				}
			}
			rr = (rr_t*)hdr->parsed;
			while(rr){
				if (rr->nameaddr.uri.len >= ISC_MARK_USERNAME_LEN &&
					strncasecmp(rr->nameaddr.uri.s,ISC_MARK_USERNAME,ISC_MARK_USERNAME_LEN)==0)	{
						LOG(L_INFO,"DEBUG:"M_NAME":isc_appserver_forward: Found S-CSCF marking <%.*s> \n",rr->nameaddr.uri.len,rr->nameaddr.uri.s);
						/* delete the header */					
						if (!del_lump(msg, hdr->name.s - msg->buf, hdr->len, 0)) {
							LOG(L_ERR, "ERROR:"M_NAME":isc_appserver_forward: Can't remove Route HF\n");
						}  
										
						/* add the new header */
						anchor = anchor_lump(msg, msg->headers->name.s - msg->buf, 0 , 0);
						header_mark.s = pkg_malloc(256);//36 should be enough
						sprintf(header_mark.s,"Route: <%.*s>\n",rr->nameaddr.uri.len,rr->nameaddr.uri.s);
						header_mark.len =strlen(header_mark.s);	
						if (!insert_new_lump_before(anchor, header_mark.s,header_mark.len,0)){
							LOG( L_ERR, "ERROR:"M_NAME":isc_appserver_forward: error creting lump for route header\n" );
						}	
					/* send the message */
					msg->dst_uri.s = pkg_malloc(rr->nameaddr.uri.len);
					memcpy(msg->dst_uri.s,rr->nameaddr.uri.s,rr->nameaddr.uri.len);
					msg->dst_uri.len=rr->nameaddr.uri.len;
					isc_tmb.t_relay(msg,0,0);
					return 0;
				}					
				rr = rr->next;
			}			
		}
		hdr = hdr->next;
	}
	
	/* In case no suitable route header found, just fwd to the given parameter */
	msg->dst_uri.len = strlen(str1);
	msg->dst_uri.s = str1;
	isc_tmb.t_relay(msg,0,0);
	LOG(L_DBG,"DEBUG:"M_NAME":isc_appserver_forward: Mirror request finished\n");
	return 0;
}
Example #15
0
static int assign_hf_do_lumping(struct sip_msg* msg,struct hdr_field* hf, struct hname_data* hname, str* value, int upd_del_fl, str* lump_upd, str* lump_del, char delim) {
	int len, i;
	char *s;
	struct lump* anchor;

	if (upd_del_fl) {
		len = value?lump_upd->len:lump_del->len;
		if (len > 0) {
			if (!del_lump(msg, (value?lump_upd->s:lump_del->s)-msg->buf, len, 0)) {
				LOG(L_ERR, "ERROR: textops: assign_hf_do_lumping: not enough memory\n");
				return -1;
			}
		}
		if (value && value->len) {
			anchor = anchor_lump(msg, lump_upd->s - msg->buf, 0, 0);
			if (anchor == 0) {
				LOG(L_ERR, "ERROR: textops: assign_hf_do_lumping: Can't get anchor\n");
				return -1;
			}

			len = 1+value->len;
			s = pkg_malloc(len);
			if (!s) {
				LOG(L_ERR, "ERROR: textops: assign_hf_do_lumping: not enough memory\n");
				return -1;
			}
			s[0]='=';
			memcpy(s+1, value->s, value->len);
			if ( (insert_new_lump_before(anchor, s, len, 0)) == 0) {
				LOG(L_ERR, "ERROR: textops: assign_hf_do_lumping: Can't insert lump\n");
				pkg_free(s);
				return -1;
			}
		}
	}
	else {
		if (!value) return -1;

		anchor = anchor_lump(msg, lump_del->s - msg->buf, 0, 0);
		if (anchor == 0) {
			LOG(L_ERR, "ERROR: textops: assign_hf_do_lumping: Can't get anchor\n");
			return -1;
		}

		len = 1+hname->param.len+(value->len?value->len+1:0);
		s = pkg_malloc(len);
		if (!s) {
			LOG(L_ERR, "ERROR: textops: assign_hf_do_lumping: not enough memory\n");
			return -1;
		}
		if (delim) {
			s[0] = delim;
			i = 1;
		}
		else {
			i = 0;
			len--;
		}
		memcpy(s+i, hname->param.s, hname->param.len);
		if (value->len) {
			s[hname->param.len+i]='=';
			memcpy(s+i+hname->param.len+1, value->s, value->len);
		}

		if ( (insert_new_lump_before(anchor, s, len, 0)) == 0) {
			LOG(L_ERR, "ERROR: textops: assign_hf_do_lumping: Can't insert lump\n");
			pkg_free(s);
			return -1;
		}
	}
	return 1;
}
Example #16
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, PCONTACT_REGISTERED,0 ,0);
//	char srcip[20];
//	str received_host;
        struct via_body* vb;
        unsigned short port;
        unsigned short proto;
	
	// 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);

        vb = cscf_get_ue_via(_m);
        port = vb->port?vb->port:5060;
        proto = vb->proto;
        
	/* 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, &vb->host, port, proto);

	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, &vb->host, port, proto);
	return 1;
error:
	/* Unlock domain */
	ul.unlock_udomain(_d, &vb->host, port, proto);
	return -1;
	
    return 1;
}
Example #17
0
int th_update_hdr_replaces(sip_msg_t *msg)
{
	struct hdr_field *hf = NULL;
	str replaces;
	str rcallid;
	struct lump* l;
	str out;

	LM_DBG("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
	if(th_param_mask_callid==0)
		return 0;

	if(!((get_cseq(msg)->method_id)&(METHOD_INVITE)))
		return 0;

	for (hf=msg->headers; hf; hf=hf->next)
	{
		if (hf->name.len==8 && strncasecmp(hf->name.s, "Replaces", 8)==0)
			break;
	}

	if(hf==NULL)
		return 0;

	replaces = hf->body;
	trim(&replaces);
	rcallid.s = replaces.s;
	for(rcallid.len=0; rcallid.len<replaces.len; rcallid.len++)
	{
		if(rcallid.s[rcallid.len]==';')
			break;
	}

	if(rcallid.len>th_callid_prefix.len
			&& strncmp(rcallid.s, th_callid_prefix.s, th_callid_prefix.len)==0)
	{
		/* value encoded - decode it */
		out.s = th_mask_decode(rcallid.s, rcallid.len,
					&th_callid_prefix, 0, &out.len);
	} else {
		/* value decoded - encode it */
		out.s = th_mask_encode(rcallid.s, rcallid.len,
				&th_callid_prefix, &out.len);
	}
	if(out.s==NULL)
	{
		LM_ERR("cannot update Replaces callid\n");
		return -1;
	}

	l=del_lump(msg, rcallid.s-msg->buf, rcallid.len, 0);
	if (l==0)
	{
		LM_ERR("failed deleting Replaces callid\n");
		pkg_free(out.s);
		return -1;
	}
	if (insert_new_lump_after(l, out.s, out.len, 0)==0) {
		LM_ERR("could not insert new lump\n");
		pkg_free(out.s);
		return -1;
	}

	return 0;
}
Example #18
0
int th_unmask_route(sip_msg_t *msg)
{
	hdr_field_t *hdr;
	struct lump* l;
	int i;
	rr_t *rr;
	str out;
	str eval;

	if(msg->route==NULL)
	{
		LM_DBG("no record route header\n");
		return 0;
	}
	hdr = msg->route;
	i = 0;
	while(hdr!=NULL) 
	{
		if (parse_rr(hdr) < 0) 
		{
			LM_ERR("failed to parse RR\n");
			return -1;
		}

		rr =(rr_t*)hdr->parsed;
		while(rr)
		{
			i++;
			if(i!=1)
			{
				if(th_get_uri_param_value(&rr->nameaddr.uri, &th_uparam_name,
							&eval)<0 || eval.len<=0)
					return -1;
	
				out.s = th_mask_decode(eval.s, eval.len,
							&th_uparam_prefix, 0, &out.len);

				if(out.s==NULL)
				{
					LM_ERR("cannot decode R %d\n", i);
					return -1;
				}
				l=del_lump(msg, rr->nameaddr.uri.s-msg->buf,
						rr->nameaddr.uri.len, 0);
				if (l==0)
				{
					LM_ERR("failed deleting R [%d]\n", i);
					pkg_free(out.s);
					return -1;
				}
				if (insert_new_lump_after(l, out.s, out.len, 0)==0){
					LM_ERR("could not insert new lump\n");
					pkg_free(out.s);
					return -1;
				}
			}
			rr = rr->next;
		}
		hdr = next_sibling_hdr(hdr);
	}

	return 0;
}
Example #19
0
int th_flip_record_route(sip_msg_t *msg, int mode)
{
	hdr_field_t *hdr;
	struct lump* l;
	int i;
	rr_t *rr;
	str out;
	int utype;
	str pval;
	int r2;
	int act;

	if(msg->record_route==NULL)
	{
		LM_DBG("no record route header\n");
		return 0;
	}
	hdr = msg->record_route;
	i = 0;
	act = 0;
	if(mode==1)
		act = 2;
	while(hdr!=NULL) 
	{
		if (parse_rr(hdr) < 0) 
		{
			LM_ERR("failed to parse RR\n");
			return -1;
		}

		rr =(rr_t*)hdr->parsed;
		while(rr)
		{
			i++;
			r2 = 0;
			utype = th_get_uri_type(&rr->nameaddr.uri, &r2, &pval);
			if(utype==0 && mode==1)
			{
				if(r2==1)
				{
					act--;
					if(act==0)
						return 0;
					utype = 1;
				} else {
					return 0;
				}
			}
			out.s = NULL;
			switch(utype) {
				case 1: /* encode */
					if(act!=0 && mode==1)
					{
						out.s = th_mask_encode(rr->nameaddr.uri.s,
							rr->nameaddr.uri.len, &th_uri_prefix, &out.len);
						if(out.s==NULL)
						{
							LM_ERR("cannot encode r-r %d\n", i);
							return -1;
						}
					}
				break;
				case 2: /* decode */
					if(mode==0)
					{
						out.s = th_mask_decode(pval.s,
							pval.len, &th_uparam_prefix, 0, &out.len);
						if(out.s==NULL)
						{
							LM_ERR("cannot decode r-r %d\n", i);
							return -1;
						}
					}
				break;
			}
			if(out.s!=NULL)
			{
				l=del_lump(msg, rr->nameaddr.uri.s-msg->buf,
						rr->nameaddr.uri.len, 0);
				if (l==0)
				{
					LM_ERR("failed deleting r-r [%d]\n", i);
					pkg_free(out.s);
					return -1;
				}
				if (insert_new_lump_after(l, out.s, out.len, 0)==0){
					LM_ERR("could not insert new lump\n");
					pkg_free(out.s);
					return -1;
				}
			}
			rr = rr->next;
		}
		hdr = next_sibling_hdr(hdr);
	}

	return 0;
}
Example #20
0
/**
 * performs the following operations at 200 OK time (early neg <-> late neg):
 *
 * - alters the callee's 200 OK message (adds the final decided codec)
 * - alters the caller's SDP (in memory), so it can be attached @ ACK
 * - opens transcoding sessions on the card if necessary
 *
 * Note: assumes all streams are on corresponding positions in both SDPs
 */
static int process_session(struct sip_msg *msg, struct sngtc_info *info, str *src,
                           str *dst, struct sdp_session_cell *s1,
                           struct sdp_session_cell *s2)
{
	struct sdp_stream_cell *sm1, *sm2;
	struct sngtc_session_list *tc_session;
	struct sngtc_codec_request request;
	struct sngtc_codec_reply *reply = NULL;
	struct codec_pair pair;
	struct lump *lump, *nl;
	struct in_addr addr;
	int rc = 0, ret, tc_on = 0;
	int idx;
	char buf[INET_ADDRSTRLEN];
	str repl;

	if (s1->next && s2->next)
		rc = process_session(msg, info, src, dst, s1->next, s2->next);
	else if (s1->next || s2->next)
		LM_ERR("endpoints have a different number of SDP sessions"
		       " - choosing min number\n");

	if (rc != 0)
		goto out;

	tc_session = info->sessions;
	for (idx = MAX_STREAMS - 1, sm1 = s1->streams, sm2 = s2->streams; sm1 && sm2;
	     sm1 = sm1->next, sm2 = sm2->next, idx--) {

		ret = match_codecs(sm1, sm2, &pair);
		codec_matches[idx] = pair;

		switch (ret) {

		case SNGTC_OFF:

			LM_DBG("NO NEED FOR TRANSCODING\n");

			/* delete codecs from 200 OK; write endpoint A codec */
			/* ip and port stay the same */
			lump = remove_sdp_stream_attrs(msg, sm2);
			if (!lump) {
				LM_ERR("failed to clear sdp codecs\n");
				return SNGTC_SDP_ERR;
			}

			LM_DBG("sdp stream:\n");
			print_sdp_stream(sm2, L_DBG);

			ret = write_sdp_stream_attr(msg, lump, pair.att2, NULL);
			if (ret != 0) {
				LM_ERR("failed to write sdp stream codec\n");
				return ret;
			}

			break;

		case SNGTC_ON:

			tc_on = 1;

			if (is_processed(info))
				goto use_existing_sessions;

			LM_DBG("TRANSCODING ([%d] %.*s:%.*s <--> [%d] %.*s:%.*s)\n",
			       pair.tc1, s1->ip_addr.len, s1->ip_addr.s, sm1->port.len,
				   sm1->port.s, pair.tc2, s2->ip_addr.len, s2->ip_addr.s,
				   sm2->port.len, sm2->port.s);

			memset(&request, 0, sizeof(request));

			request.usr_priv = NULL;

			/* Codec, ms, IP and port for side A */
			request.a.codec_id = pair.tc1;
			request.a.ms = 0;
			sprintf(buf, "%.*s", s1->ip_addr.len, s1->ip_addr.s);
			ret = inet_pton(AF_INET, buf, &addr);
			if (ret != 1) {
				LM_ERR("failed to convert ip %s to binary form (%d)\n",
				       s1->ip_addr.s, ret);
				return SNGTC_ERR;
			}
			request.a.host_ip = htonl(addr.s_addr);
			request.a.host_netmask = (unsigned int)-1;
			if (str2int(&sm1->port, &request.a.host_udp_port) != 0)
				LM_ERR("Failed to parse integer stored in port str '%.*s'\n",
						sm1->port.len, sm1->port.s);

			/* Codec, ms, IP and port for side B */
			request.b.codec_id = pair.tc2;
			request.b.ms = 0;
			sprintf(buf, "%.*s", s2->ip_addr.len, s2->ip_addr.s);
			ret = inet_pton(AF_INET, buf, &addr);
			if (ret != 1) {
				LM_ERR("failed to convert ip %.*s to binary form (%d)\n",
				       s2->ip_addr.len, s2->ip_addr.s, ret);
				return SNGTC_ERR;
			}
			request.b.host_ip = htonl(addr.s_addr);
			request.b.host_netmask = (unsigned int)-1;
			if (str2int(&sm2->port, &request.b.host_udp_port) != 0)
				LM_ERR("Failed to parse integer stored in port str '%.*s'\n",
						sm2->port.len, sm2->port.s);

			LM_DBG("Transcoding request: %d:%d <--> %d:%d\n", request.a.host_ip,
			       request.a.host_udp_port, request.b.host_ip,
			       request.b.host_udp_port);

			reply = create_transcoding_session(&request, info);
			if (!reply) {
				LM_ERR("Failed to create a transcoding session on the card\n");
				return SNGTC_TC_ERR;
			}

use_existing_sessions:

			LM_DBG("NEW TC SESSION!\n");

			if (is_processed(info)) {
				reply = tc_session->reply;
				tc_session = tc_session->next;
			}

			codec_matches[idx].reply = reply;

			/**
			 * delete codecs from 200 OK
			 * write the common codec
			 * replace IP with ip of Sangoma card
			 * replace port with endpoint A newly opened port on card
			 */
			lump = remove_sdp_stream_attrs(msg, sm2);
			if (!lump) {
				LM_ERR("failed to clear sdp codecs\n");
				return SNGTC_SDP_ERR;
			}

			nl = del_lump(msg, s2->ip_addr.s - msg->buf, s2->ip_addr.len, 0);
			if (!nl) {
				LM_ERR("failed to add del lump\n");
				return SNGTC_ERR;
			}

			if (pkg_str_dup(&repl, &card_ip_b) != 0) {
				LM_ERR("failed to dup in pkg mem\n");
				return SNGTC_ERR;
			}

			if (!insert_new_lump_after(nl, repl.s, repl.len, HDR_OTHER_T)) {
				LM_ERR("failed to insert lump with codec result\n");
				return SNGTC_ERR;
			}

			if (replace_sdp_stream_port(msg, sm2,
			                            reply->a.codec_udp_port) != 0) {
				LM_ERR("failed to rewrite sdp stream port\n");
				return SNGTC_ERR;
			}

			if (write_sdp_stream_attr(msg, lump, pair.att1, reply) != 0) {
				LM_ERR("failed to write sdp stream codecs\n");
				return SNGTC_ERR;
			}

			break;

		case SNGTC_UNSUP_CODECS:

			LM_ERR("endpoints have no common codecs and at least one side "
			       "contains only unsupported Sangoma codecs\n");

			LM_ERR("caller:\n");
			print_sdp_stream(sm1, L_ERR);

			LM_ERR("callee:\n");
			print_sdp_stream(sm2, L_ERR);
			return SNGTC_SDP_ERR;

		case SNGTC_BAD_SDP:

			LM_ERR("received bogus sdp with no attributes\n");

			LM_ERR("caller:\n");
			print_sdp_stream(sm1, L_ERR);

			LM_ERR("callee:\n");
			print_sdp_stream(sm2, L_ERR);
			return SNGTC_SDP_ERR;
		}
	}

	if (tc_on) {
		LM_DBG("transcoding: ON\n");

		memcpy(dst->s + dst->len, src->s, s1->ip_addr.s - src->s);
		dst->len += s1->ip_addr.s - src->s;
		dst->len += sprintf(dst->s + dst->len, "%.*s",
		                    card_ip_a.len, card_ip_a.s);
		src->s += s1->ip_addr.s - src->s + s1->ip_addr.len;
	} else
		LM_DBG("transcoding: OFF\n");

	rc |= process_stream(s1->streams, s2->streams, src, dst, MAX_STREAMS - 1);
out:
	return rc;
}
Example #21
0
/*!
 * \brief Previous hop was a loose router, handle this case
 * \param _m SIP message
 * \param preloaded do we have a preloaded route set
 * \return -1 on failure, 1 on success
 */
static inline int after_loose(struct sip_msg* _m, int preloaded)
{
    struct hdr_field* hdr;
    struct sip_uri puri;
    rr_t* rt;
    int res;
    int status = RR_DRIVEN;
    str uri;
    struct socket_info *si;
    int uri_is_myself, next_is_strict;
    int use_ob = 0;

    hdr = _m->route;
    rt = (rr_t*)hdr->parsed;
    uri = rt->nameaddr.uri;

    /* reset rr handling static vars for safety in error case */
    routed_msg_id = 0;

    if (parse_uri(uri.s, uri.len, &puri) < 0) {
        LM_ERR("failed to parse the first route URI\n");
        return RR_ERROR;
    }

    next_is_strict = is_strict(&puri.params);
    routed_params = puri.params;
    uri_is_myself = is_myself(&puri);

    /* IF the URI was added by me, remove it */
    if (uri_is_myself>0)
    {
        LM_DBG("Topmost route URI: '%.*s' is me\n",
               uri.len, ZSW(uri.s));
        /* set the hooks for the params */
        routed_msg_id = _m->id;

        if ((use_ob = process_outbound(_m, puri.user)) < 0) {
            LM_INFO("failed to process outbound flow-token\n");
            return FLOW_TOKEN_BROKEN;
        }

        if (!rt->next) {
            /* No next route in the same header, remove the whole header
             * field immediately
             */
            if (!del_lump(_m, hdr->name.s - _m->buf, hdr->len, 0)) {
                LM_ERR("failed to remove Route HF\n");
                return RR_ERROR;
            }

            res = find_next_route(_m, &hdr);
            if (res < 0) {
                LM_ERR("failed to find next route\n");
                return RR_ERROR;
            }
            if (res > 0) { /* No next route found */
                LM_DBG("No next URI found\n");
                status = (preloaded ? NOT_RR_DRIVEN : RR_DRIVEN);
                goto done;
            }
            rt = (rr_t*)hdr->parsed;
        } else rt = rt->next;

        if (enable_double_rr && is_2rr(&puri.params)) {
            /* double route may occure due different IP and port, so force as
             * send interface the one advertise in second Route */
            if (parse_uri(rt->nameaddr.uri.s,rt->nameaddr.uri.len,&puri)<0) {
                LM_ERR("failed to parse the double route URI\n");
                return RR_ERROR;
            }

            if (!use_ob) {
                si = grep_sock_info( &puri.host, puri.port_no, puri.proto);
                if (si) {
                    set_force_socket(_m, si);
                } else {
                    if (enable_socket_mismatch_warning)
                        LM_WARN("no socket found for match second RR\n");
                }
            }

            if (!rt->next) {
                /* No next route in the same header, remove the whole header
                 * field immediately */
                if (!del_lump(_m, hdr->name.s - _m->buf, hdr->len, 0)) {
                    LM_ERR("failed to remove Route HF\n");
                    return RR_ERROR;
                }
                res = find_next_route(_m, &hdr);
                if (res < 0) {
                    LM_ERR("failed to find next route\n");
                    return RR_ERROR;
                }
                if (res > 0) { /* No next route found */
                    LM_DBG("no next URI found\n");
                    status = (preloaded ? NOT_RR_DRIVEN : RR_DRIVEN);
                    goto done;
                }
                rt = (rr_t*)hdr->parsed;
            } else rt = rt->next;
        }

        uri = rt->nameaddr.uri;
        if (parse_uri(uri.s, uri.len, &puri) < 0) {
            LM_ERR("failed to parse the first route URI\n");
            return RR_ERROR;
        }
    } else {
#ifdef ENABLE_USER_CHECK
        /* check if it the ignored user */
        if(uri_is_myself < 0)
            return NOT_RR_DRIVEN;
#endif
        LM_DBG("Topmost URI is NOT myself\n");
        routed_params.s = NULL;
        routed_params.len = 0;
    }

    LM_DBG("URI to be processed: '%.*s'\n", uri.len, ZSW(uri.s));
    if (next_is_strict) {
        LM_DBG("Next URI is a strict router\n");
        if (handle_sr(_m, hdr, rt) < 0) {
            LM_ERR("failed to handle strict router\n");
            return RR_ERROR;
        }
    } else {
        /* Next hop is loose router */
        LM_DBG("Next URI is a loose router\n");

        if (!use_ob) {
            if(get_maddr_uri(&uri, &puri)!=0) {
                LM_ERR("checking maddr failed\n");
                return RR_ERROR;
            }

            if (set_dst_uri(_m, &uri) < 0) {
                LM_ERR("failed to set dst_uri\n");
                return RR_ERROR;
            }
            /* dst_uri changed, so it makes sense to re-use the current uri for
            forking */
            ruri_mark_new(); /* re-use uri for serial forking */
        }

        /* There is a previous route uri which was 2nd uri of mine
         * and must be removed here */
        if (rt != hdr->parsed) {
            if (!del_lump(_m, hdr->body.s - _m->buf,
                          rt->nameaddr.name.s - hdr->body.s, 0)) {
                LM_ERR("failed to remove Route HF\n");
                return RR_ERROR;
            }
        }
    }

done:
    if (use_ob == 1)
        status = RR_OB_DRIVEN;

    /* run RR callbacks only if we have Route URI parameters */
    if(routed_params.len > 0)
        run_rr_callbacks( _m, &routed_params );
    return status;
}
Example #22
0
int save(struct sip_msg* _m, char* _d, char* _f, char* _s)
{
	struct sip_msg* msg = _m;
	struct cell* t = NULL;
	contact_t* _c;
	contact_t* reply_c = NULL;
	contact_t* request_c = NULL;
	int st;
	int ret;
	int requested_exp = 0;
	int enforced_exp = 0;
	int_str val;
	struct lump* l;
	char* p;
	char forced_binding_buf[MAX_FORCED_BINDING_LEN];
	str forced_binding = {NULL, 0};
	str *binding_uri;

	if(_m->first_line.type != SIP_REPLY)
		return save_aux(_m, NULL, _d, _f, _s);

	memset(&val, 0, sizeof(int_str));
	if(!tmb.t_gett) {
		LM_ERR("TM module not loaded - can not save on reply\n");
		return -1;
	}
	t = tmb.t_gett();
	if(!t || t==T_UNDEFINED) {
		LM_ERR("Transaction not created on Register - can not save on reply\n");
		return -1;
	}
	msg = t->uas.request;
	if(!msg) {
		LM_ERR("NULL request - can not save on reply\n");
		return -1;
	}

	if (parse_message(_m) < 0) return -1;
	if (check_contacts(_m, &st) > 0) return -1;
	if (parse_message(msg) < 0) return -1;
	if (check_contacts(msg, &st) > 0) return -1;

	/* msg - request
	   _m  - reply 
	*/
	request_c = get_first_contact(msg);
	if(request_c) {
		/* For now, we deal only with the first contact
		 * FIXME: implement multiple contact handling - see check_contacts() */
		if(!request_c->expires || !request_c->expires->body.len) {
			if (((exp_body_t*)(msg->expires->parsed))->valid) {
				requested_exp = ((exp_body_t*)(msg->expires->parsed))->val;
			} else {
				LM_WARN("No expired defined\n");
			}
		} else {
			if (str2int(&(request_c->expires->body), (unsigned int*)&requested_exp)<0) {
				LM_ERR("unable to get expires from [%.*s]\n",
					request_c->expires->body.len, request_c->expires->body.s);
				return -1;
			}
		}
		LM_DBG("Binding received from client [%.*s] with requested expires [%d]\n",
				request_c->uri.len, request_c->uri.s, requested_exp);

		/* We will use the Contact from request:
		 *  - check if a modified contact was set in avp */
		if (mct_avp_name >= 0 &&
			search_first_avp(mct_avp_type,mct_avp_name,&val,0)
			&& val.s.len > 0) {
			LM_DBG("Binding sent to upper registrar [%.*s]\n",
					val.s.len, val.s.s);
			binding_uri = &val.s;
		} else {
			binding_uri = &request_c->uri;
		}

		if (requested_exp) {
			/* Let's get the contact from reply */
			_c = get_first_contact(_m);
			while (_c) {
				if (compare_uris(binding_uri, NULL, &_c->uri, NULL) == 0) {
					if(_c->expires && _c->expires->body.len) {
						if(str2int(&(_c->expires->body),
							(unsigned int*)&enforced_exp)<0) {
							LM_ERR("unable to get expires from [%.*s]\n",
								_c->expires->body.len,
								_c->expires->body.s);
							return -1;
						}
						LM_DBG("Binding received from upper registrar"
							" [%.*s] with imposed expires [%d]\n",
							_c->uri.len, _c->uri.s, enforced_exp);
						reply_c = _c;
						forced_binding.len = request_c->uri.len + 11 +
									reply_c->expires->body.len;
						if (forced_binding.len <= MAX_FORCED_BINDING_LEN) {
							forced_binding.s = forced_binding_buf;
							forced_binding_buf[0] = '<';
							memcpy(&forced_binding_buf[1],
								request_c->uri.s,
								request_c->uri.len);
							memcpy(&forced_binding_buf[request_c->uri.len + 1],
								">;expires=", 10);
							memcpy(&forced_binding_buf[request_c->uri.len + 11],
								reply_c->expires->body.s,
								reply_c->expires->body.len);
							LM_DBG("forcing binding [%.*s]\n",
								forced_binding.len,
								forced_binding.s);
							break;
						} else {
							LM_ERR("forced binding to BIG:"
								" %d > MAX_FORCED_BINDING_LEN\n",
								forced_binding.len);
							return -1;
						}
					}
				} else {
					LM_DBG("Unmatched binding [%.*s]\n",
							_c->uri.len, _c->uri.s);
				}
				_c = get_next_contact(_c);
			}
		}
		ret = save_aux(msg, forced_binding.s?&forced_binding:NULL, _d, _f, _s);
	} else {
		LM_DBG("No Contact in request => this is an interogation\n");
		ret = 1;
	}


	/* if the contact was changed in register - put the modif value */
	if(request_c && requested_exp && val.s.s) {
		if(reply_c) {
			LM_DBG("replacing contact uri [%.*s] with [%.*s]\n",
				reply_c->uri.len, reply_c->uri.s,
				request_c->uri.len, request_c->uri.s);
			/* replace with what was received in Register */
			/* reply_c->uri - now contains the initial received value */
			if((l=del_lump(_m, reply_c->uri.s - _m->buf, reply_c->uri.len, 0))==0) {
				LM_ERR("Failed to delete contact uri lump\n");
				ret = -1;
				goto done;
			}
			p = pkg_malloc( request_c->uri.len);
			if (p==0) {
				LM_ERR("no more pkg mem\n");
				ret = -1;
				goto done;
			}
			memcpy( p, request_c->uri.s, request_c->uri.len );
			if (insert_new_lump_after( l, p, request_c->uri.len, 0)==0) {
				LM_ERR("insert new lump failed\n");
				pkg_free(p);
				ret =-1;
				goto done;
			}
		}
	}

done:
	clean_msg_clone(t->uas.request, t->uas.request, t->uas.end_request);

	return ret;
}
Example #23
0
/**
 * sngtc_caller_answer - attaches an SDP body to ACK requests
 */
static int sngtc_caller_answer(struct sip_msg *msg)
{
	char *p;
	str body;
	struct dlg_cell *dlg;
	struct lump *lump;
	struct sngtc_info *info;
	int len;

	LM_DBG("processing ACK\n");

	if (get_body(msg, &body) != 0 || body.len > 0) {
		LM_ERR("ACK should not contain a SDP body\n");
		return SNGTC_ERR;
	}

	dlg = dlg_binds.get_dlg();
	if (!dlg) {
		LM_ERR("failed to fetch current dialog\n");
		return SNGTC_ERR;
	}

	/* get the SDP body from the INVITE which was mangled at 200 OK */
	if (dlg_binds.fetch_dlg_value(dlg, &dlg_key_sngtc_info, &body, 0) != 0) {
		LM_ERR("failed to fetch caller sdp\n");
		return SNGTC_ERR;
	}

	info = *(struct sngtc_info **)(body.s);

	/* duplicate the SDP in pkg mem for the lumps mechanism */
	if (pkg_str_dup(&body, &info->modified_caller_sdp) != 0) {
		LM_ERR("failed to dup in pkg mem\n");
		return SNGTC_ERR;
	}

	LM_DBG("Duplicated SDP: '%.*s'\n", body.len, body.s);

	lump = anchor_lump(msg, msg->content_length->name.s - msg->buf, 0);
	if (!lump) {
		LM_ERR("failed to insert anchor lump\n");
		return SNGTC_ERR;
	}

	p = pkg_malloc(SDP_CONTENT_TYPE_LEN);
	if (!p) {
		LM_ERR("no more pkg memory\n");
		return SNGTC_ERR;
	}

	/* add the Content-Type header */

	memcpy(p, "Content-Type: application/sdp\r\n", SDP_CONTENT_TYPE_LEN);

	if (!insert_new_lump_before(lump, p, SDP_CONTENT_TYPE_LEN, 0)) {
		LM_ERR("failed to insert Content-Type lump\n");
		return SNGTC_ERR;
	}

	LM_DBG("blen: %d\n", msg->content_length->body.len);

	lump = del_lump(msg, msg->content_length->body.s - msg->buf,
	                msg->content_length->body.len, HDR_OTHER_T);
	if (!lump) {
		LM_ERR("failed to insert del lump for the content length\n");
		return SNGTC_ERR;
	}

	p = pkg_malloc(CONTENT_LEN_DIGITS);
	if (!p) {
		LM_ERR("no more pkg memory\n");
		return SNGTC_ERR;
	}

	LM_DBG("len: %d\n", body.len);

	len = sprintf(p, "%d", body.len);

	if (!insert_new_lump_after(lump, p, len, HDR_OTHER_T)) {
		LM_ERR("failed to insert Content-Length lump\n");
		return SNGTC_ERR;
	}

	lump = anchor_lump(msg, msg->len - CRLF_LEN, 0);
	if (!lump) {
		LM_ERR("failed to insert anchor lump\n");
		return SNGTC_ERR;
	}

	if (!insert_new_lump_before(lump, body.s, body.len, 0)) {
		LM_ERR("failed to insert SDP body lump\n");
		return SNGTC_ERR;
	}

	return 1;
}
Example #24
0
/**
 * sngtc_offer - will remove the SDP body of an early negotiation INVITE and
 * store it in the newly created dialog as a dlg_val.
 *
 * @return: 1 on success, negative on failure
 */
static int sngtc_offer(struct sip_msg *msg)
{
	struct hdr_field *hf;
	struct lump *lump;
	struct dlg_cell *dlg;
	struct sngtc_info *info = NULL;
	str body, totag, st;

	if (dlg_binds.create_dlg(msg, 0) < 0) {
		LM_ERR("failed to create dialog\n");
		return SNGTC_ERR;
	}

	dlg = dlg_binds.get_dlg();
	if (!dlg) {
		LM_ERR("failed to fetch current dialog\n");
		return SNGTC_ERR;
	}

	if (get_body(msg, &body) != 0 || body.len <= 0) {
		LM_ERR("can only do transcoding for early negotiation INVITES\n");
		return SNGTC_SDP_ERR;
	}

	totag = get_to(msg)->tag_value;

	/* INVITE retransmissions will skip this part */
	if (dlg_binds.fetch_dlg_value(dlg, &dlg_key_sngtc_info, &st, 0) != 0) {

		if (store_sngtc_info(dlg, &body) != 0) {
			LM_ERR("failed to create sngtc info struct\n");
			return SNGTC_ERR;
		}

		/* register a callback to free the above */
		if (dlg_binds.register_dlgcb(dlg,
			                         DLGCB_EXPIRED|DLGCB_FAILED|DLGCB_TERMINATED,
		    sngtc_dlg_terminated, NULL, NULL) != 0) {

			LM_ERR("failed to register dialog callback\n");
			return SNGTC_ERR;
		}

	/* for re-INVITES, just recreate the struct sngtc_info */
	} else if (totag.s && totag.len != 0) {
		info = *(struct sngtc_info **)(st.s);

		free_transcoding_sessions(info->sessions);
		if (info->caller_sdp.s)
			shm_free(info->caller_sdp.s);
		if (info->modified_caller_sdp.s)
			shm_free(info->modified_caller_sdp.s);

		if (store_sngtc_info(dlg, &body) != 0) {
			LM_ERR("failed to create sngtc info struct\n");
			return SNGTC_ERR;
		}

		shm_free(info);
	}

	LM_DBG("SDP body:\n");
	LM_DBG("%.*s\n", body.len, body.s);

	hf = msg->content_type;

	/* delete the Content-Type header, we're setting up late negotiation */
	lump = del_lump(msg, hf->name.s - msg->buf, hf->len, HDR_OTHER_T);
	if (!lump) {
		LM_ERR("no more pkg mem\n");
		return SNGTC_ERR;
	}

	/* trim the entire SDP body */
	lump = del_lump(msg, body.s - msg->buf, body.len, HDR_OTHER_T);
	if (!lump) {
		LM_ERR("no more pkg mem\n");
		return SNGTC_ERR;
	}

	return 1;
}
Example #25
0
/*
 * Send a request using data from the dialog structure
 */
int t_uac(str* method, str* headers, str* body, dlg_t* dialog,
				transaction_cb cb, void* cbp,release_tmcb_param release_func)
{
	union sockaddr_union to_su, new_to_su;
	struct cell *new_cell;
	struct cell *backup_cell;
	struct retr_buf *request;
	static struct sip_msg *req;
	struct usr_avp **backup;
	char *buf, *buf1;
	int buf_len, buf_len1;
	int ret, flags, sflag_bk;
	int backup_route_type;
	int sip_msg_len;
	unsigned int hi;
	struct socket_info *new_send_sock;
	str h_to, h_from, h_cseq, h_callid;
	struct proxy_l *proxy, *new_proxy;
	unsigned short dst_changed;

	ret=-1;

	/*** added by dcm
	 * - needed by external ua to send a request within a dlg
	 */
	if(!dialog->hooks.next_hop && w_calculate_hooks(dialog)<0)
		goto error3;

	if(dialog->obp.s)
		dialog->hooks.next_hop = &dialog->obp;

	LM_DBG("next_hop=<%.*s>\n",dialog->hooks.next_hop->len,
			dialog->hooks.next_hop->s);

	/* calculate the socket corresponding to next hop */
	proxy = uri2proxy( dialog->hooks.next_hop,
		dialog->send_sock ? dialog->send_sock->proto : PROTO_NONE );
	if (proxy==0)  {
		ret=E_BAD_ADDRESS;
		goto error3;
	}
	/* use the first address */
	hostent2su( &to_su,
		&proxy->host, proxy->addr_idx, proxy->port ? proxy->port:SIP_PORT);

	/* check/discover the send socket */
	if (dialog->send_sock) {
		/* if already set, the protocol of send sock must have the 
		   the same type as the proto required by destination URI */
		if (proxy->proto != dialog->send_sock->proto)
			dialog->send_sock = NULL;
	}
	if (dialog->send_sock==NULL) {
		/* get the send socket */
		dialog->send_sock = get_send_socket( NULL/*msg*/, &to_su, proxy->proto);
		if (!dialog->send_sock) {
			LM_ERR("no corresponding socket for af %d\n", to_su.s.sa_family);
			ser_error = E_NO_SOCKET;
			goto error2;
		}
	}
	LM_DBG("sending socket is %.*s \n",
		dialog->send_sock->name.len,dialog->send_sock->name.s);


	/* ***** Create TRANSACTION and all related  ***** */
	new_cell = build_cell( NULL/*msg*/, 1/*full UAS clone*/);
	if (!new_cell) {
		ret=E_OUT_OF_MEM;
		LM_ERR("short of cell shmem\n");
		goto error2;
	}

	/* pass the transaction flags from dialog to transaction */
	new_cell->flags |= dialog->T_flags;

	/* add the callback the transaction for LOCAL_COMPLETED event */
	flags = TMCB_LOCAL_COMPLETED;
	/* Add also TMCB_LOCAL_RESPONSE_OUT if provisional replies are desired */
	if (pass_provisional_replies || pass_provisional(new_cell))
		flags |= TMCB_LOCAL_RESPONSE_OUT;
	if(cb && insert_tmcb(&(new_cell->tmcb_hl),flags,cb,cbp,release_func)!=1){
		ret=E_OUT_OF_MEM;
		LM_ERR("short of tmcb shmem\n");
		goto error2;
	}

	if (method->len==INVITE_LEN && memcmp(method->s, INVITE, INVITE_LEN)==0)
		new_cell->flags |= T_IS_INVITE_FLAG;
	new_cell->flags |= T_IS_LOCAL_FLAG;

	request = &new_cell->uac[0].request;
	if (dialog->forced_to_su.s.sa_family == AF_UNSPEC)
		request->dst.to = to_su;
	else
		request->dst.to = dialog->forced_to_su;
	request->dst.send_sock = dialog->send_sock;
	request->dst.proto = dialog->send_sock->proto;
	request->dst.proto_reserved1 = 0;

	hi=dlg2hash(dialog);
	LOCK_HASH(hi);
	insert_into_hash_table_unsafe(new_cell, hi);
	UNLOCK_HASH(hi);

	/* copy AVPs into transaction */
	new_cell->user_avps = dialog->avps;
	dialog->avps = NULL;


	/* ***** Create the message buffer ***** */
	buf = build_uac_req(method, headers, body, dialog, 0, new_cell, &buf_len);
	if (!buf) {
		LM_ERR("failed to build message\n");
		ret=E_OUT_OF_MEM;
		goto error1;
	}

	if (local_rlist.a) {
		LM_DBG("building sip_msg from buffer\n");
		req = buf_to_sip_msg(buf, buf_len, dialog);
		if (req==NULL) {
			LM_ERR("failed to build sip_msg from buffer\n");
		} else {
			/* set this transaction as active one */
			backup_cell = get_t();
			set_t( new_cell );
			/* set transaction AVP list */
			backup = set_avp_list( &new_cell->user_avps );
			/* backup script flags */
			sflag_bk = getsflags();
			/* disable parallel forking */
			set_dset_state( 0 /*disable*/);

			/* run the route */
			swap_route_type( backup_route_type, LOCAL_ROUTE);
			run_top_route( local_rlist.a, req);
			set_route_type( backup_route_type );

			/* transfer current message context back to t */
			new_cell->uac[0].br_flags = getb0flags(req);
			/* restore the prevoius active transaction */
			set_t( backup_cell );

			set_dset_state( 1 /*enable*/);
			setsflagsval(sflag_bk);
			set_avp_list( backup );

			/* check for changes - if none, do not regenerate the buffer */
			dst_changed = 1;
			if (req->new_uri.s || req->force_send_socket!=dialog->send_sock ||
			req->dst_uri.len != dialog->hooks.next_hop->len ||
			memcmp(req->dst_uri.s,dialog->hooks.next_hop->s,req->dst_uri.len) ||
			(dst_changed=0)==0 || req->add_rm || req->body_lumps){

				new_send_sock = NULL;
				/* do we also need to change the destination? */
				if (dst_changed) {
					/* calculate the socket corresponding to next hop */
					new_proxy = uri2proxy(
						req->dst_uri.s ? &(req->dst_uri) : &req->new_uri,
						PROTO_NONE );
					if (new_proxy==0)
						goto abort_update;
					/* use the first address */
					hostent2su( &new_to_su,
						&new_proxy->host, new_proxy->addr_idx,
						new_proxy->port ? new_proxy->port:SIP_PORT);
					/* get the send socket */
					new_send_sock = get_send_socket( req, &new_to_su,
						new_proxy->proto);
					if (!new_send_sock) {
						free_proxy( new_proxy );
						pkg_free( new_proxy );
						LM_ERR("no socket found for the new destination\n");
						goto abort_update;
					}
				}

				/* if interface change, we need to re-build the via */
				if (new_send_sock && new_send_sock != dialog->send_sock) {
					LM_DBG("Interface change in local route -> "
						"rebuilding via\n");
					if (!del_lump(req,req->h_via1->name.s - req->buf,
					req->h_via1->len,0)) {
						LM_ERR("Failed to remove initial via \n");
						goto abort_update;
					}

					memcpy(req->add_to_branch_s,req->via1->branch->value.s,
						req->via1->branch->value.len);
					req->add_to_branch_len = req->via1->branch->value.len;

					/* update also info about new destination and send sock */
					dialog->send_sock = new_send_sock;
					free_proxy( proxy );
					pkg_free( proxy );
					proxy = new_proxy;
					request->dst.send_sock = new_send_sock;
					request->dst.proto = new_send_sock->proto;
					request->dst.proto_reserved1 = 0;

					/* build the shm buffer now */
					set_init_lump_flags(LUMPFLAG_BRANCH);
					buf1 = build_req_buf_from_sip_req(req,
						(unsigned int*)&buf_len1,
						new_send_sock, new_send_sock->proto,
						MSG_TRANS_SHM_FLAG);
					reset_init_lump_flags();
					del_flaged_lumps( &req->add_rm, LUMPFLAG_BRANCH);

				} else {

					LM_DBG("Change in local route -> rebuilding buffer\n");
					/* build the shm buffer now */
					buf1 = build_req_buf_from_sip_req(req,
						(unsigned int*)&buf_len1,
						dialog->send_sock, dialog->send_sock->proto,
						MSG_TRANS_SHM_FLAG|MSG_TRANS_NOVIA_FLAG);
					/* now as it used, hide the original VIA header */
					del_lump(req,req->h_via1->name.s - req->buf,
						req->h_via1->len, 0);

				}

				if (!buf1) {
					LM_ERR("no more shm mem\n");
					/* keep original buffer */
					goto abort_update;
				}
				/* update shortcuts */
				if(!req->add_rm && !req->new_uri.s) {
					/* headers are not affected, simply tranlate */
					new_cell->from.s = new_cell->from.s - buf + buf1;
					new_cell->to.s = new_cell->to.s - buf + buf1;
					new_cell->callid.s = new_cell->callid.s - buf + buf1;
					new_cell->cseq_n.s = new_cell->cseq_n.s - buf + buf1;
				} else {
					/* use heavy artilery :D */
					if (extract_ftc_hdrs( buf1, buf_len1, &h_from, &h_to,
					&h_cseq, &h_callid)!=0 ) {
						LM_ERR("failed to update shortcut pointers\n");
						shm_free(buf1);
						goto abort_update;
					}
					new_cell->from = h_from;
					new_cell->to = h_to;
					new_cell->callid = h_callid;
					new_cell->cseq_n = h_cseq;
				}
				/* here we rely on how build_uac_req()
				   builds the first line */
				new_cell->uac[0].uri.s = buf1 +
					req->first_line.u.request.method.len + 1;
				new_cell->uac[0].uri.len = GET_RURI(req)->len;

				/* update also info about new destination and send sock */
				if (new_send_sock)
					request->dst.to = new_to_su;

				shm_free(buf);
				buf = buf1;
				buf_len = buf_len1;
				/* use new buffer */
			} else {
				/* no changes over the message, buffer is already generated,
				   just hide the original VIA for potential further branches */
				del_lump(req,req->h_via1->name.s-req->buf,req->h_via1->len,0);
			}
abort_update:
			/* save the SIP message into transaction */
			new_cell->uas.request = sip_msg_cloner( req, &sip_msg_len, 1);
			if (new_cell->uas.request==NULL) {
				/* reset any T triggering */
				new_cell->on_negative = 0;
				new_cell->on_reply = 0;
			} else {
				new_cell->uas.end_request=
					((char*)new_cell->uas.request)+sip_msg_len;
			}
			/* no parallel support in UAC transactions */
			new_cell->on_branch = 0;
			free_sip_msg(req);
		}
	}

	/* for DNS based failover, copy the DNS proxy into transaction */
	if (!disable_dns_failover) {
		new_cell->uac[0].proxy = shm_clone_proxy( proxy, 1/*do_free*/);
		if (new_cell->uac[0].proxy==NULL)
			LM_ERR("failed to store DNS info -> no DNS based failover\n");
	}

	new_cell->method.s = buf;
	new_cell->method.len = method->len;

	request->buffer.s = buf;
	request->buffer.len = buf_len;
	new_cell->nr_of_outgoings++;

	if(last_localT) {
		*last_localT = new_cell;
		REF_UNSAFE(new_cell);
	}

	if (SEND_BUFFER(request) == -1) {
		LM_ERR("attempt to send to '%.*s' failed\n",
			dialog->hooks.next_hop->len,
			dialog->hooks.next_hop->s);
	}

	if (method->len==ACK_LEN && memcmp(method->s, ACK, ACK_LEN)==0 ) {
		t_release_transaction(new_cell);
	} else {
		start_retr(request);
	}

	free_proxy( proxy );
	pkg_free( proxy );

	return 1;

error1:
	LOCK_HASH(hi);
	remove_from_hash_table_unsafe(new_cell);
	UNLOCK_HASH(hi);
	free_cell(new_cell);
error2:
	free_proxy( proxy );
	pkg_free( proxy );
error3:
	return ret;
}
Example #26
0
static inline int after_loose(struct sip_msg* _m, int preloaded)
{
	struct hdr_field* hdr;
	struct sip_uri puri;
	struct sip_uri puri2;
	rr_t* rt;
	int res;
	int status;
#ifdef ENABLE_USER_CHECK
	int ret;
#endif
	str uri;
	struct socket_info *si;
	int force_ss = 0;

	hdr = _m->route;
	rt = (rr_t*)hdr->parsed;
	uri = rt->nameaddr.uri;

	if (parse_uri(uri.s, uri.len, &puri) < 0) {
		LM_ERR("failed to parse the first route URI\n");
		return RR_ERROR;
	}

	/* IF the URI was added by me, remove it */
#ifdef ENABLE_USER_CHECK
	ret=is_myself(&puri.user, &puri.host, puri.port_no);
	if (ret>0)
#else
	if (is_myself(&puri.host, puri.port_no))
#endif
	{
		LM_DBG("Topmost route URI: '%.*s' is me\n",
			uri.len, ZSW(uri.s));
		/* set the hooks for the params -bogdan */
		ctx_rrparam_set( &puri.params );

		/* if last route in header, gonna get del_lumped now,
		 * if not, it will be taken care of later
		 * Mark it now as deleted */
		rt->deleted = 1;

		if (!rt->next) {
			/* No next route in the same header, remove the whole header
			 * field immediately
			 */
			if (!del_lump(_m, hdr->name.s - _m->buf, hdr->len, 0)) {
				LM_ERR("failed to remove Route HF\n");
				return RR_ERROR;
			}

			rt->deleted = 1;

			res = find_next_route(_m, &hdr);
			if (res < 0) {
				LM_ERR("failed to find next route\n");
				return RR_ERROR;
			}
			if (res > 0) { /* No next route found */
				LM_DBG("No next URI found!\n");
				status = (preloaded ? NOT_RR_DRIVEN : RR_DRIVEN);

				/*same case as LL , if there is no next route*/
				ctx_routing_set( ROUTING_LL );
				force_ss = 1;

				goto done;
			}
			rt = (rr_t*)hdr->parsed;
		} else rt = rt->next;

		if (enable_double_rr && is_2rr(&puri.params)) {
			force_ss = 0;
			/* double route may occure due different IP and port, so force as
			 * send interface the one advertise in second Route */
			if (parse_uri(rt->nameaddr.uri.s,rt->nameaddr.uri.len,&puri)<0) {
				LM_ERR("failed to parse the double route URI\n");
				return RR_ERROR;
			}
			set_sip_defaults( puri.port_no, puri.proto);
			si = grep_sock_info( &puri.host, puri.port_no, puri.proto);
			if (si) {
				_m->force_send_socket = si;
			} else {
				if (enable_socket_mismatch_warning)
					LM_WARN("no socket found to match 2nd RR [%d][%.*s:%d]\n",
						puri.proto, puri.host.len, puri.host.s, puri.port_no);
			}

			rt->deleted = 1;

			if (!rt->next) {
				/* No next route in the same header, remove the whole header
				 * field immediately */
				if (!del_lump(_m, hdr->name.s - _m->buf, hdr->len, 0)) {
					LM_ERR("failed to remove Route HF\n");
					return RR_ERROR;
				}

				res = find_next_route(_m, &hdr);
				if (res < 0) {
					LM_ERR("failed to find next route\n");
					return RR_ERROR;
				}
				if (res > 0) { /* No next route found */
					LM_DBG("no next URI found\n");
					status = (preloaded ? NOT_RR_DRIVEN : RR_DRIVEN);

					/* same case as LL , if there is no next route */
					ctx_routing_set( ROUTING_LL );

					goto done;
				}
				rt = (rr_t*)hdr->parsed;
			} else rt = rt->next;
		} else {
			force_ss = 1;
		}

		uri = rt->nameaddr.uri;
		if (parse_uri(uri.s, uri.len, &puri2) < 0) {
			LM_ERR("failed to parse the first route URI\n");
			return RR_ERROR;
		}
	} else {
#ifdef ENABLE_USER_CHECK
		/* check if it the ignored user */
		if(ret < 0)
			return NOT_RR_DRIVEN;
#endif
		LM_DBG("Topmost URI is NOT myself\n");
		memcpy(&puri2, &puri, sizeof(struct sip_uri));
	}

	LM_DBG("URI to be processed: '%.*s'\n", uri.len, ZSW(uri.s));
	if (is_strict(&puri2.params)) {
		LM_DBG("Next URI is a strict router\n");

		ctx_routing_set( ROUTING_LS );
		if (handle_sr(_m, hdr, rt) < 0) {
			LM_ERR("failed to handle strict router\n");
			return RR_ERROR;
		}
	} else {
		/* Next hop is loose router */
		LM_DBG("Next URI is a loose router\n");

		ctx_routing_set( ROUTING_LL );

		if(get_maddr_uri(&uri, &puri2)!=0) {
			LM_ERR("checking maddr failed\n");
			return RR_ERROR;
		}
		if (set_dst_uri(_m, &uri) < 0) {
			LM_ERR("failed to set dst_uri\n");
			return RR_ERROR;
		}

		/* There is a previous route uri which was 2nd uri of mine
		 * and must be removed here */
		if (rt != hdr->parsed) {
			if (!del_lump(_m, hdr->body.s - _m->buf,
			rt->nameaddr.name.s - hdr->body.s, 0)) {
				LM_ERR("failed to remove Route HF\n");
				return RR_ERROR;
			}

			((rr_t *)hdr->parsed)->deleted = 1;
		}
	}
	status = RR_DRIVEN;

done:
	if (force_ss && !preloaded)
		_m->force_send_socket = _m->rcv.bind_address;
	/* run RR callbacks -bogdan */
	run_rr_callbacks( _m, &puri.params );
	return status;
}
Example #27
0
/*!
 * \brief Previous hop was a strict router, handle this case
 * \param _m SIP message
 * \return -1 on error, 1 on success
 */
static inline int after_strict(struct sip_msg* _m)
{
    int res, rem_len;
    struct hdr_field* hdr;
    struct sip_uri puri;
    rr_t* rt, *prev;
    char* rem_off;
    str uri;
    struct socket_info *si;

    hdr = _m->route;
    rt = (rr_t*)hdr->parsed;
    uri = rt->nameaddr.uri;

    /* reset rr handling static vars for safety in error case */
    routed_msg_id = 0;
    routed_params.s = NULL;
    routed_params.len = 0;

    if (parse_uri(uri.s, uri.len, &puri) < 0) {
        LM_ERR("failed to parse the first route URI\n");
        return RR_ERROR;
    }

    if ( enable_double_rr && is_2rr(&puri.params) && is_myself(&puri)) {
        /* double route may occure due different IP and port, so force as
         * send interface the one advertise in second Route */
        si = grep_sock_info( &puri.host, puri.port_no, puri.proto);
        if (si) {
            set_force_socket(_m, si);
        } else {
            if (enable_socket_mismatch_warning)
                LM_WARN("no socket found for match second RR\n");
        }

        if (!rt->next) {
            /* No next route in the same header, remove the whole header
             * field immediately
             */
            if (!del_lump(_m, hdr->name.s - _m->buf, hdr->len, 0)) {
                LM_ERR("failed to remove Route HF\n");
                return RR_ERROR;
            }
            res = find_next_route(_m, &hdr);
            if (res < 0) {
                LM_ERR("searching next route failed\n");
                return RR_ERROR;
            }
            if (res > 0) { /* No next route found */
                LM_DBG("after_strict: No next URI found\n");
                return NOT_RR_DRIVEN;
            }
            rt = (rr_t*)hdr->parsed;
        } else rt = rt->next;

        /* parse the new found uri */
        uri = rt->nameaddr.uri;
        if (parse_uri(uri.s, uri.len, &puri) < 0) {
            LM_ERR("failed to parse URI\n");
            return RR_ERROR;
        }
    }

    /* set the hooks for the param
     * important note: RURI is already parsed by the above function, so
     * we just used it without any checking */
    routed_msg_id = _m->id;
    routed_params = _m->parsed_uri.params;

    if (is_strict(&puri.params)) {
        LM_DBG("Next hop: '%.*s' is strict router\n", uri.len, ZSW(uri.s));
        /* Previous hop was a strict router and the next hop is strict
         * router too. There is no need to save R-URI again because it
         * is saved already. In fact, in this case we will behave exactly
         * like a strict router. */

        /* Note: when there is only one Route URI left (endpoint), it will
         * always be a strict router because endpoints don't use ;lr parameter
         * In this case we will simply put the URI in R-URI and forward it,
         * which will work perfectly */
        if(get_maddr_uri(&uri, &puri)!=0) {
            LM_ERR("failed to check maddr\n");
            return RR_ERROR;
        }
        if (rewrite_uri(_m, &uri) < 0) {
            LM_ERR("failed to rewrite request URI\n");
            return RR_ERROR;
        }

        if (rt->next) {
            rem_off = hdr->body.s;
            rem_len = rt->next->nameaddr.name.s - hdr->body.s;
        } else {
            rem_off = hdr->name.s;
            rem_len = hdr->len;
        }
        if (!del_lump(_m, rem_off - _m->buf, rem_len, 0)) {
            LM_ERR("failed to remove Route HF\n");
            return RR_ERROR;
        }
    } else {
        LM_DBG("Next hop: '%.*s' is loose router\n",
               uri.len, ZSW(uri.s));

        if(get_maddr_uri(&uri, &puri)!=0) {
            LM_ERR("failed to check maddr\n");
            return RR_ERROR;
        }
        if (set_dst_uri(_m, &uri) < 0) {
            LM_ERR("failed to set dst_uri\n");
            return RR_ERROR;
        }

        /* Next hop is a loose router - Which means that is is not endpoint yet
         * In This case we have to recover from previous strict routing, that
         * means we have to find the last Route URI and put in in R-URI and
         * remove the last Route URI. */
        if (rt != hdr->parsed) {
            /* There is a previous route uri which was 2nd uri of mine
             * and must be removed here */
            rem_off = hdr->body.s;
            rem_len = rt->nameaddr.name.s - hdr->body.s;
            if (!del_lump(_m, rem_off - _m->buf, rem_len, 0)) {
                LM_ERR("failed to remove Route HF\n");
                return RR_ERROR;
            }
        }


        res = find_rem_target(_m, &hdr, &rt, &prev);
        if (res < 0) {
            LM_ERR("searching for last Route URI failed\n");
            return RR_ERROR;
        } else if (res > 0) {
            /* No remote target is an error */
            return RR_ERROR;
        }

        uri = rt->nameaddr.uri;
        if(get_maddr_uri(&uri, 0)!=0) {
            LM_ERR("checking maddr failed\n");
            return RR_ERROR;
        }
        if (rewrite_uri(_m, &uri) < 0) {
            LM_ERR("failed to rewrite R-URI\n");
            return RR_ERROR;
        }

        /* The first character if uri will be either '<' when it is the
         * only URI in a Route header field or ',' if there is more than
         * one URI in the header field */
        LM_DBG("The last route URI: '%.*s'\n", rt->nameaddr.uri.len,
               ZSW(rt->nameaddr.uri.s));

        if (prev) {
            rem_off = prev->nameaddr.name.s + prev->len;
            rem_len = rt->nameaddr.name.s + rt->len - rem_off;
        } else {
            rem_off = hdr->name.s;
            rem_len = hdr->len;
        }
        if (!del_lump(_m, rem_off - _m->buf, rem_len, 0)) {
            LM_ERR("failed to remove Route HF\n");
            return RR_ERROR;
        }
    }

    /* run RR callbacks only if we have Route URI parameters */
    if(routed_params.len > 0)
        run_rr_callbacks( _m, &routed_params );

    return RR_DRIVEN;
}
Example #28
0
int th_mask_contact(sip_msg_t *msg)
{
	struct lump* l;
	str out;
	str in;
	char *p;
	contact_t *c;

	if(msg->contact==NULL) 
	{
		LM_DBG("no contact header\n");
		return 0;
	}

	if(parse_contact(msg->contact) < 0)
	{
		LM_ERR("failed parsing contact header\n");
		return -1;
	}
	
	c = ((contact_body_t*)msg->contact->parsed)->contacts;
	in = c->uri;

	out.s = th_mask_encode(in.s, in.len, &th_uri_prefix, &out.len);
	if(out.s==NULL)
	{
		LM_ERR("cannot encode contact uri\n");
		return -1;
	}
	if(*(in.s-1)!='<')
	{
		/* add < > around contact uri if not there */
		p = (char*)pkg_malloc(out.len+3);
		if(p==NULL)
		{
			LM_ERR("failed to get more pkg\n");
			pkg_free(out.s);
			return -1;
		}
		*p = '<';
		strncpy(p+1, out.s, out.len);
		p[out.len+1] = '>';
		p[out.len+2] = '\0';
		pkg_free(out.s);
		out.s = p;
		out.len += 2;
	}
				
	l=del_lump(msg, in.s-msg->buf, in.len, 0);
	if (l==0)
	{
		LM_ERR("failed deleting contact uri\n");
		pkg_free(out.s);
		return -1;
	}
	if (insert_new_lump_after(l, out.s, out.len, 0)==0) {
		LM_ERR("could not insert new lump\n");
		pkg_free(out.s);
		return -1;
	}

	return 0;
}
Example #29
0
/**
 * @brief forward SIP reply statelessy with different code and reason text
 */
static int w_sl_forward_reply(sip_msg_t* msg, str* code, str* reason)
{
	char oldscode[3];
	int oldncode;
	int ret;
	struct lump	*ldel = NULL;
	struct lump	*ladd = NULL;
	char *rbuf;

	if(msg->first_line.type!=SIP_REPLY) {
		LM_ERR("invalid SIP message type\n");
		return -1;
	}
	if(code!=NULL) {
		if(code->len!=3) {
			LM_ERR("invalid reply code value %.*s\n", code->len, code->s);
			return -1;
		}
		if(msg->first_line.u.reply.status.s[0]!=code->s[0]) {
			LM_ERR("reply code class cannot be changed\n");
			return -1;
		}
		if(code->s[1]<'0' || code->s[1]>'9'
				|| code->s[2]<'0' || code->s[2]>'9') {
			LM_ERR("invalid reply code value %.*s!\n", code->len, code->s);
			return -1;
		}
	}
	if(reason!=NULL && reason->len<=0) {
		LM_ERR("invalid reply reason value\n");
		return -1;
	}
	/* backup old values */
	oldscode[0] = msg->first_line.u.reply.status.s[0];
	oldscode[1] = msg->first_line.u.reply.status.s[1];
	oldscode[2] = msg->first_line.u.reply.status.s[2];
	oldncode = msg->first_line.u.reply.statuscode;
	if(code!=NULL) {
		/* update status code directly in msg buffer */
		msg->first_line.u.reply.statuscode = (code->s[0]-'0')*100
			+ (code->s[1]-'0')*10 + code->s[2]-'0';
		msg->first_line.u.reply.status.s[0] = code->s[0];
		msg->first_line.u.reply.status.s[1] = code->s[1];
		msg->first_line.u.reply.status.s[2] = code->s[2];

	}
	if(reason!=NULL) {
		ldel = del_lump(msg,
					msg->first_line.u.reply.reason.s - msg->buf,
					msg->first_line.u.reply.reason.len,
					0);
		if (ldel==NULL) {
			LM_ERR("failed to add del lump\n");
			ret = -1;
			goto restore;
		}
		rbuf = (char *)pkg_malloc(reason->len);
		if (rbuf==NULL) {
			LM_ERR("not enough memory\n");
			ret = -1;
			goto restore;
		}
		memcpy(rbuf, reason->s, reason->len);
		ladd = insert_new_lump_after(ldel, rbuf, reason->len, 0);
		if (ladd==0) {
			LOG(L_ERR, "failed to add reason lump: %.*s\n",
				reason->len, reason->s);
			pkg_free(rbuf);
			ret = -1;
			goto restore;
		}
	}
	ret = forward_reply_nocb(msg);
restore:
	if(reason!=NULL) {
		if(ldel!=NULL) {
			remove_lump(msg, ldel);
		}
		if(ladd!=NULL) {
			remove_lump(msg, ladd);
		}
	}
	if(code!=NULL) {
		msg->first_line.u.reply.statuscode = oldncode;
		msg->first_line.u.reply.status.s[0] = oldscode[0];
		msg->first_line.u.reply.status.s[1] = oldscode[1];
		msg->first_line.u.reply.status.s[2] = oldscode[2];
	}
	return (ret==0)?1:ret;
}
Example #30
0
int th_unmask_via(sip_msg_t *msg, str *cookie)
{
	hdr_field_t *hdr;
	struct via_body *via;
	struct via_body *via2;
	struct via_param *vp;
	struct lump* l;
	int i;
	str out;
	int vlen;

	i=0;
	for(hdr=msg->h_via1; hdr; hdr=next_sibling_hdr(hdr))
	{
		for(via=(struct via_body*)hdr->parsed; via; via=via->next)
		{
			i++;
			LM_DBG("=======via[%d]\n", i);
			LM_DBG("hdr: [%.*s]\n", via->hdr.len, via->hdr.s);
			vlen = th_skip_rw(via->name.s, via->bsize);
			LM_DBG("body: %d: [%.*s]\n", vlen, vlen, via->name.s);
			if(i!=1)
			{
				vp = th_get_via_param(via, &th_vparam_name);
				if(vp==NULL)
				{
					LM_ERR("cannot find param in via %d\n", i);
					return -1;
				}
				if(i==2)
					out.s = th_mask_decode(vp->value.s, vp->value.len,
							&th_vparam_prefix, CRLF_LEN+1, &out.len);
				else
					out.s = th_mask_decode(vp->value.s, vp->value.len,
							&th_vparam_prefix, 0, &out.len);
				if(out.s==NULL)
				{
					LM_ERR("cannot encode via %d\n", i);
					return -1;
				}
					
				LM_DBG("+body: %d: [%.*s]\n", out.len, out.len, out.s);
				if(i==2)
				{
					via2=pkg_malloc(sizeof(struct via_body));
					if (via2==0)
					{
						LM_ERR("out of memory\n");
						pkg_free(out.s);
						return -1;

					}
					
					memset(via2, 0, sizeof(struct via_body));
					memcpy(out.s+out.len, CRLF, CRLF_LEN);
					out.s[out.len+CRLF_LEN]='X';
					if(parse_via(out.s, out.s+out.len+CRLF_LEN+1, via2)==NULL)
					{
						LM_ERR("error parsing decoded via2\n");
						free_via_list(via2);
						pkg_free(out.s);
						return -1;
					}
					out.s[out.len] = '\0';
					vp = th_get_via_param(via2, &th_cookie_name);
					if(vp==NULL)
					{
						LM_ERR("cannot find cookie in via2\n");
						free_via_list(via2);
						pkg_free(out.s);
						return -1;
					}
					*cookie = vp->value;
					free_via_list(via2);
				}
				l=del_lump(msg, via->name.s-msg->buf, vlen, 0);
				if (l==0)
				{
					LM_ERR("failed deleting via [%d]\n", i);
					pkg_free(out.s);
					return -1;
				}
				if (insert_new_lump_after(l, out.s, out.len, 0)==0)
				{
					LM_ERR("could not insert new lump\n");
					pkg_free(out.s);
					return -1;
				}
			}
		}
	}

	return 0;
}