Esempio n. 1
0
int recordroute_diff(struct sip_msg *req,struct sip_msg *resp)
{
   struct hdr_field *hf;
   rr_t *rr1;
   int i,j,k;
   i=j=k=0;
   /* count how many record-route bodies come in the response*/
   /* this does not work, I think because of siblings
   for(hf=resp->record_route;hf;hf=hf->sibling,j=0){
   */
   for(hf=resp->headers;hf;hf=hf->next,j=0){
      if(hf->type != HDR_RECORDROUTE_T)
	 continue;
      if(!hf->parsed){
	 if(0>parse_rr(hf))
	    goto error;
	 j=1;
      }
      for(rr1=hf->parsed;rr1;rr1=rr1->next){
	 i++;
      }
      if(j){
	 free_rr((rr_t**)(void*)&hf->parsed);
	 hf->parsed=NULL;
      }
   }
   /*
   for(hf=req->record_route;hf;hf=hf->sibling,j=0){
      */
   for(hf=req->headers;hf;hf=hf->next,j=0){
      if(hf->type != HDR_RECORDROUTE_T)
	 continue;
      if(!hf->parsed){
	 if(0>parse_rr(hf))
	    goto error;
	 j=1;
      }
      for(rr1=hf->parsed;rr1;rr1=rr1->next){
	 k++;
      }
      if(j){
	 free_rr((rr_t**)(void*)&hf->parsed);
	 hf->parsed=NULL;
      }
   }
   return i-k;
error:
   return -1;
}
Esempio n. 2
0
/**
 * Returns the first entry of the P-Associated-URI header.
 * @param msg - the SIP message to look into
 * @param public_id - the public identity to be filled with the result
 * @returns 1 on success or 0 on failure
 */
int cscf_get_first_p_associated_uri(struct sip_msg *msg,str *public_id)
{
	struct hdr_field *h;
	rr_t *r;
	public_id->s=0;public_id->len=0;
	
	if (!msg) return 0;
	if (parse_headers(msg, HDR_EOH_F, 0)<0){
		LOG(L_ERR,"ERR:"M_NAME":cscf_get_p_associated_uri: error parsing headers\n");
		return 0;
	}
	h = msg->headers;
	while(h){
		if (h->name.len==16 && strncasecmp(h->name.s,"P-Associated-URI",16)==0)
			break;
		h = h->next;
	}
	if (!h){
		LOG(L_DBG,"DBG:"M_NAME":cscf_get_p_associated_uri: Header P-Associated-URI not found\n");
		return 0;
	}
	if (parse_rr(h)<0){
		LOG(L_ERR,"ERR:"M_NAME":cscf_get_p_associated_uri: Error parsing as Route header\n");
		return 0;
	}
	r = (rr_t*)h->parsed;
	h->type = HDR_ROUTE_T;
	
	if (r) {
		*public_id=r->nameaddr.uri;
		return 1;
	}
	else
		return 0;
}
Esempio n. 3
0
/*!
 * \brief Copy flow-token from top-Route: to a string
 *
 * Copy the user part of the top-Route: to a string (allocating private memory
 * for this).
 * \param token where the user-part of the top-Route: will be copied to
 * \param _m the SIP message to extract the top-Route: from
 * \return 0 on success, negative on failure
 */
static int copy_flow_token(str *token, struct sip_msg *_m)
{
    rr_t *rt;
    struct sip_uri puri;

    if (_m->route
            || (parse_headers(_m, HDR_ROUTE_F, 0) != -1 && _m->route)) {
        if (parse_rr(_m->route) < 0) {
            LM_ERR("parsing Route: header body\n");
            return -1;
        }
        rt = (rr_t *) _m->route->parsed;
        if (!rt) {
            LM_ERR("empty Route:\n");
            return -1;
        }
        if (parse_uri(rt->nameaddr.uri.s, rt->nameaddr.uri.len,
                      &puri) < 0) {
            LM_ERR("parsing Route-URI\n");
            return -1;
        }

        token->s = pkg_malloc(puri.user.len * sizeof(char));
        if (token->s == NULL) {
            LM_ERR("allocating memory\n");
            return -1;
        }
        memcpy(token->s, puri.user.s, puri.user.len);
        token->len = puri.user.len;
        return 0;
    }

    LM_ERR("no Route: headers found\n");
    return -1;
}
Esempio n. 4
0
/**
 * Finds if the message contains the orig parameter in the first Route header
 * @param msg - the SIP message
 * @param str1 - not used
 * @param str2 - not used
 * @returns #CSCF_RETURN_TRUE if yes, else #CSCF_RETURN_FALSE
 */
int cscf_has_originating(struct sip_msg *msg,char *str1,char *str2)
{
	//int ret=CSCF_RETURN_FALSE;
	struct hdr_field *h;
	str* uri;
	rr_t *r;

	if (parse_headers(msg, HDR_ROUTE_F, 0)<0){
		LM_DBG("I_originating: error parsing headers\n");
		return CSCF_RETURN_FALSE;
	}
	h = msg->route;
	if (!h){
		LM_DBG("I_originating: Header Route not found\n");
		return CSCF_RETURN_FALSE;
	}
	if (parse_rr(h)<0){
		LM_DBG("I_originating: Error parsing as Route header\n");
		return CSCF_RETURN_FALSE;
	}
	r = (rr_t*)h->parsed;

	uri = &r->nameaddr.uri;
	struct sip_uri puri;
	if (parse_uri(uri->s, uri->len, &puri) < 0) {
		LM_DBG( "I_originating: Error while parsing the first route URI\n");
		return -1;
	}
	if (puri.params.len < 4) return CSCF_RETURN_FALSE;
	int c = 0;
	int state = 0; 
	while (c < puri.params.len) {
		switch (puri.params.s[c]) {
		case 'o': if (state==0) state=1;
		break;
		case 'r': if (state==1) state=2;
		break;
		case 'i': if (state==2) state=3;
		break;
		case 'g': if (state==3) state=4;
		break;
		case ' ':
		case '\t':
		case '\r':
		case '\n':
		case ',':
		case ';':
			if (state==4) return CSCF_RETURN_TRUE;
			state=0;
			break;
		case '=': if (state==4) return CSCF_RETURN_TRUE;
		state=-1;
		break;
		default: state=-1;
		}
		c++;
	}

	return state==4 ? CSCF_RETURN_TRUE : CSCF_RETURN_FALSE;
}
Esempio n. 5
0
static int get_direction(struct sip_msg* msg)
{
	int ret;
	if (parse_orig_ruri(msg) < 0) {
		return -1;
	}

	if (!msg->parsed_orig_ruri_ok) {
		ERR("Error while parsing original Request-URI\n");
		return -1;
	}

	ret = check_self(&msg->parsed_orig_ruri.host,
			 msg->parsed_orig_ruri.port_no ? msg->parsed_orig_ruri.port_no : SIP_PORT, 0);/* match all protos*/
	if (ret < 0) return -1;
	if (ret > 0) {
		     /* Route is in ruri */
		return check_ftag(msg, &msg->first_line.u.request.uri);
	} else {
		if (msg->route) {
			if (parse_rr(msg->route) < 0) {
				ERR("Error while parsing Route HF\n");
				return -1;
			}
		        ret = check_ftag(msg, &((rr_t*)msg->route->parsed)->nameaddr.uri);
			if (msg->route->parsed) free_rr((rr_t**)(void*)&msg->route->parsed);
			return ret;
		} else {
			DBG("No Route headers found\n");
			return -1;
		}
	}
}
Esempio n. 6
0
str* get_route_set(struct sip_msg *msg,int *nr_routes)
{
	static str uris[MAX_RR_HDRS];
	struct hdr_field *it;
	rr_t *p;
	int n = 0;

	if (msg == NULL || msg->route == NULL)
	{
		LM_ERR("null sip msg or no route headers\n");
		return 0;
	}

	if (routing_type == ROUTING_SS || routing_type == ROUTING_LS)
	{
		/* must manually insert RURI, as it was part
		 * of the route deleted to make up for strict routing */
		uris[n++] = msg->new_uri;
	}

	it = msg->route;
	while (it != NULL)
	{
		if (parse_rr(it) < 0)
		{
			LM_ERR("failed to parse RR\n");
			return 0;
		}

		p = (rr_t*)it->parsed;
		while (p)
		{
			if (p->deleted == 0)
			{
				uris[n++] = p->nameaddr.uri;
				if(n==MAX_RR_HDRS)
				{
					LM_ERR("too many RR\n");
					return 0;
				}
			}
			else
				LM_DBG("Route [%.*s] has been deleted\n",p->nameaddr.uri.len,
						p->nameaddr.uri.s);
			p = p->next;
		}
		it = it->sibling;
	}


	/* if SS - remove last route */
	if (routing_type == ROUTING_SS)
		n--;

	if (nr_routes)
		*nr_routes = n;

	return uris;
}
Esempio n. 7
0
/**
 * Returns the content of the P-Associated-URI header
 * Public_id is pkg_alloced and should be later freed.
 * Inside values are not duplicated.
 * @param msg - the SIP message to look into
 * @param public_id - array to be allocated and filled with the result
 * @param public_id_cnt - the size of the public_id array
 * @param is_shm - msg from shared memory
 * @returns 1 on success or 0 on error
 */
int cscf_get_p_associated_uri(struct sip_msg *msg, str **public_id,
		int *public_id_cnt, int is_shm) {
	struct hdr_field *h;
	rr_t *r, *r2;
	*public_id = 0;
	*public_id_cnt = 0;

	if (!msg)
		return 0;
	if (parse_headers(msg, HDR_EOH_F, 0) < 0) {
		LM_ERR("error parsing headers\n");
		return 0;
	}
	h = msg->headers;
	while (h) {
		if (h->name.len == 16
				&& strncasecmp(h->name.s, "P-Associated-URI", 16) == 0) {
			break;
		}
		h = h->next;
	}
	if (!h) {
		LM_DBG("Header P-Associated-URI not found\n");
		return 0;
	}
	if (parse_rr(h) < 0) {
		LM_DBG("Error parsing as Route header\n");
		return 0;
	}
	r = (rr_t*) h->parsed;
	h->type = HDR_ROUTE_T;
	*public_id_cnt = 0;
	r2 = r;
	while (r2) {
		(*public_id_cnt) = (*public_id_cnt) + 1;
		r2 = r2->next;
	}
	*public_id = pkg_malloc(sizeof(str)*(*public_id_cnt));
	if (!public_id) {
		LM_ERR("Error out of pkg memory");
		return 0;
	}
	r2 = r;
	*public_id_cnt = 0;
	while (r2) {
		(*public_id)[(*public_id_cnt)] = r2->nameaddr.uri;
		(*public_id_cnt) = (*public_id_cnt) + 1;
		r2 = r2->next;
	}

	if (is_shm) {
		r = (rr_t*) h->parsed;
		h->parsed = 0;
		free_rr(&r);
	}

	return 1;
}
Esempio n. 8
0
int th_mask_record_route(sip_msg_t *msg)
{
	hdr_field_t *hdr;
	struct lump* l;
	int i;
	rr_t *rr;
	str out;

	if(msg->record_route==NULL)
	{
		LM_DBG("no record route header\n");
		return 0;
	}
	hdr = msg->record_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)
			{
				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;
				}
				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;
}
Esempio n. 9
0
static void cares_callback(void *arg, int status, unsigned char *abuf, int alen) {
	int i;
	unsigned int ancount, nscount, arcount;
	const unsigned char *aptr;

#ifdef DEBUG
	printf("cares_callback: status=%i, alen=%i\n", status, alen);
#endif
	if (status != ARES_SUCCESS) {
		if (verbose > 1)
			printf("ares failed: %s\n", ares_strerror(status));
		return;
	}

	ancount = DNS_HEADER_ANCOUNT(abuf);
	nscount = DNS_HEADER_NSCOUNT(abuf);
	arcount = DNS_HEADER_ARCOUNT(abuf);
	
#ifdef DEBUG
	printf("ancount: %i, nscount: %i, arcount: %i\n", ancount, nscount, arcount);
#endif

	/* safety check */
	if (alen < NS_HFIXEDSZ)
		return;
	aptr = abuf + NS_HFIXEDSZ;

	aptr = skip_query(aptr, abuf, alen);

	for (i = 0; i < ancount && caadr == 0; i++) {
		if (ca_tmpname == NULL)
			aptr = parse_rr(aptr, abuf, alen);
		else
			aptr = skip_rr(aptr, abuf, alen);
	}
	if (caadr == 0) {
		for (i = 0; i < nscount; i++) {
			aptr = skip_rr(aptr, abuf, alen);
		}
		for (i = 0; i < arcount && caadr == 0; i++) {
			aptr = parse_rr(aptr, abuf, alen);
		}
	}
}
Esempio n. 10
0
static int parse_rr_header(struct sip_msg *msg)
{
        if ( !msg->record_route && ( parse_headers(msg,HDR_RECORDROUTE_F,0) == -1)) {
                LM_ERR("bad msg or missing Record-Route header\n");
                return -1;
        }

	if (!msg->record_route) {
		LM_DBG("No Record-Route header field found\n");
		return -1;
	}

	return parse_rr(msg->record_route);
}
Esempio n. 11
0
/*
 * Parse the message and find first occurrence of
 * Route header field. The function returns -1 or -2
 * on a parser error, 0 if there is a Route HF and
 * 1 if there is no Route HF.
 */
static inline int find_first_route(struct sip_msg* _m)
{
	if (parse_headers(_m, HDR_ROUTE_F, 0) == -1) {
		LOG(L_ERR, "find_first_route: Error while parsing headers\n");
		return -1;
	} else {
		if (_m->route) {
			if (parse_rr(_m->route) < 0) {
				LOG(L_ERR, "find_first_route: Error while parsing Route HF\n");
				return -2;
			}
			return 0;
		} else {
			DBG("find_first_route: No Route headers found\n");
			return 1;
		}
	}
}
Esempio n. 12
0
/*!
 * \brief Parse the message and find first occurrence of Route header field.
 * \param _m SIP message
 * \return -1 or -2 on a parser error, 0 if there is a Route HF and 1 if there is no Route HF
 */
static inline int find_first_route(struct sip_msg* _m)
{
    if (parse_headers(_m, HDR_ROUTE_F, 0) == -1) {
        LM_ERR("failed to parse headers\n");
        return -1;
    } else {
        if (_m->route) {
            if (parse_rr(_m->route) < 0) {
                LM_ERR("failed to parse Route HF\n");
                return -2;
            }
            return 0;
        } else {
            LM_DBG("No Route headers found\n");
            return 1;
        }
    }
}
Esempio n. 13
0
/**
 * Looks for the P-Asserted-Identity header and extracts its content
 * @param msg - the sip message
 * @returns the asserted identity
 */
str cscf_get_asserted_identity(struct sip_msg *msg)
{
	name_addr_t id;
	struct hdr_field *h;
	rr_t *r;
	memset(&id,0,sizeof(name_addr_t));
	if (!msg) return id.uri;
	if (parse_headers(msg, HDR_EOH_F, 0)<0) {
		return id.uri;
	}
	h = msg->headers;
	while(h)
	{
		if (h->name.len == s_asserted_identity.len  &&
			strncasecmp(h->name.s,s_asserted_identity.s,s_asserted_identity.len)==0)
		{
			if (parse_rr(h)<0){
				//This might be an old client
				LOG(L_CRIT,"WARN:"M_NAME":cscf_get_asserted_identity: P-Asserted-Identity header must contain a Nameaddr!!! Fix the client!\n");
				id.name.s = h->body.s;
				id.name.len = 0;
				id.len = h->body.len;
				id.uri = h->body;
				while(id.uri.len && (id.uri.s[0]==' ' || id.uri.s[0]=='\t' || id.uri.s[0]=='<')){
					id.uri.s = id.uri.s+1;
					id.uri.len --;
				}
				while(id.uri.len && (id.uri.s[id.uri.len-1]==' ' || id.uri.s[id.uri.len-1]=='\t' || id.uri.s[id.uri.len-1]=='>')){
					id.uri.len--;
				}
				return id.uri;	
			}
			r = (rr_t*) h->parsed;
			id = r->nameaddr;			
			free_rr(&r);
			h->parsed=r;
			//LOG(L_RIT,"%.*s",id.uri.len,id.uri.s);
			return id.uri;
		}
		h = h->next;
	}
	return id.uri;
}
Esempio n. 14
0
int tps_route_direction(sip_msg_t *msg)
{
	rr_t *rr;
	struct sip_uri puri;
	str ftn = {"ftag", 4};
	str ftv = {0, 0};

	if(get_from(msg)->tag_value.len<=0)
	{
		LM_ERR("failed to get from header tag\n");
		return -1;
	}
	if(msg->route==NULL)
	{
		LM_DBG("no route header - downstream\n");
		return 0;
	}
	if (parse_rr(msg->route) < 0) 
	{
		LM_ERR("failed to parse route header\n");
		return -1;
	}

	rr =(rr_t*)msg->route->parsed;

	if (parse_uri(rr->nameaddr.uri.s, rr->nameaddr.uri.len, &puri) < 0) {
		LM_ERR("failed to parse the first route URI\n");
		return -1;
	}
	if(tps_get_param_value(&puri.params, &ftn, &ftv)!=0)
		return 0;

	if(get_from(msg)->tag_value.len!=ftv.len
			|| strncmp(get_from(msg)->tag_value.s, ftv.s, ftv.len)!=0)
	{
		LM_DBG("ftag mismatch\n");
		return 1;
	}
	LM_DBG("ftag match\n");
	return 0;
}
Esempio n. 15
0
int 
dump_rr(struct iso_directory_record * idr){
	int len;
	char * pnt;

	len = idr->length[0] & 0xff;
	len -= (sizeof(struct iso_directory_record) - sizeof(idr->name));
	len -= idr->name_len[0];
	pnt = (char *) idr;
	pnt += (sizeof(struct iso_directory_record) - sizeof(idr->name));
	pnt += idr->name_len[0];

	if((idr->name_len[0] & 1) == 0){
		pnt++;
		len--;
	};

	rr_goof = 0;
	parse_rr(pnt, len, 0);
	return rr_goof;
}
Esempio n. 16
0
/*
 * Create a copy of route set either in normal or reverse order
 */
static inline int get_route_set(struct sip_msg* _m, rr_t** _rs, unsigned char _order)
{
	struct hdr_field* ptr;
	rr_t* last, *p, *t;
	
	last = 0;

	ptr = _m->record_route;
	while(ptr) {
		if (ptr->type == HDR_RECORDROUTE_T) {
			if (parse_rr(ptr) < 0) {
				LOG(L_ERR, "get_route_set(): Error while parsing Record-Route body\n");
				goto error;
			}

			p = (rr_t*)ptr->parsed;
			if (shm_duplicate_rr(&t, p) < 0) {
				LOG(L_ERR, "get_route_set(): Error while duplicating rr_t\n");
				goto error;
			}
			if (!*_rs) *_rs = t;
			if (last) last->next = t;
			last = t;
			while (last->next) last = last->next; /* !!! there may be more routes in one hdr field !!! */

		}
		ptr = ptr->next;
	}
	if ((*_rs) && (_order != NORMAL_ORDER)) {
		/* better to revert the route outside of cycle above */
		*_rs = revert_route(*_rs);
	}
	
	return 0;

 error:
	shm_free_rr(_rs);
	return -1;
}
Esempio n. 17
0
/**
 *	Retrieves the mark from message.
 *		- the marking should be in a header like described before
 *	@param msg - SIP mesage to mark
 *  @param mark - mark to load into
 *	@returns 1 if found, 0 if not
 */
int isc_mark_get_from_msg(struct sip_msg *msg, isc_mark *mark) {
	struct hdr_field *hdr;
	rr_t *rr;
	str x;
	LM_DBG("isc_mark_get_from_msg: Trying to get the mark from the message \n");

	memset(mark, 0, sizeof(isc_mark));

	parse_headers(msg, HDR_EOH_F, 0);
	hdr = msg->headers;
	while (hdr) {
		if (hdr->type == HDR_ROUTE_T) {
			if (!hdr->parsed) {
				if (parse_rr(hdr) < 0) {
					LM_ERR("isc_mark_get_from_msg: Error while parsing Route HF\n");
					hdr = hdr->next;
					continue;
				}
			}
			rr = (rr_t*) hdr->parsed;
			while (rr) {
				x = rr->nameaddr.uri;
				if (x.len >= ISC_MARK_USERNAME_LEN + 1 + isc_my_uri.len
						&& strncasecmp(x.s, ISC_MARK_USERNAME,
								ISC_MARK_USERNAME_LEN) == 0
						&& strncasecmp(x.s + ISC_MARK_USERNAME_LEN + 1,
								isc_my_uri.s, isc_my_uri.len) == 0) {
					LM_DBG("isc_mark_get_from_msg: Found <%.*s>\n",	x.len, x.s);
					isc_mark_get(x, mark);
					return 1;
				}
				rr = rr->next;
			}
		}
		hdr = hdr->next;
	}
	return 0;
}
Esempio n. 18
0
/*
 * Return the URI of the topmost Route-Header.
 */
static int
pv_get_route_uri_f(struct sip_msg *msg, pv_param_t *param,
		  pv_value_t *res)
{
	struct hdr_field* hdr;
	rr_t* rt;
	str uri;

	if (!msg) {
		LM_ERR("No message?!?\n");
		return -1;
	}

	/* Parse the message until the First-Route-Header: */
	if (parse_headers(msg, HDR_ROUTE_F, 0) == -1) {
		LM_ERR("while parsing message\n");
		return -1;
    	}
	
	if (!msg->route) {
		LM_INFO("No route header present.\n");
		return -1;
	}
	hdr = msg->route;

	/* Parse the contents of the header: */
	if (parse_rr(hdr) == -1) {
		LM_ERR("Error while parsing Route header\n");
                return -1;
	}


	/* Retrieve the Route-Header */	
	rt = (rr_t*)hdr->parsed;
	uri = rt->nameaddr.uri;

	return pv_get_strval(msg, param, res, &uri);
}
Esempio n. 19
0
/*!
 * \brief Find and parse next Route header field
 * \param _m SIP message
 * \param _hdr SIP header
 * \return negative on failure, 0 if the Route header was already parsed, 1 if no next
 * Route header could be found
 */
static inline int find_next_route(struct sip_msg* _m, struct hdr_field** _hdr)
{
    struct hdr_field* ptr;

    ptr = (*_hdr)->next;

    /* Try to find already parsed Route headers */
    while(ptr) {
        if (ptr->type == HDR_ROUTE_T) goto found;
        ptr = ptr->next;
    }

    /* There are no already parsed Route headers, try to find next
     * occurrence of Route header
     */
    if (parse_headers(_m, HDR_ROUTE_F, 1) == -1) {
        LM_ERR("failed to parse headers\n");
        return -1;
    }

    if ((_m->last_header->type!=HDR_ROUTE_T) || (_m->last_header==*_hdr)) {
        LM_DBG("No next Route HF found\n");
        return 1;
    }

    ptr = _m->last_header;

found:
    if (parse_rr(ptr) < 0) {
        LM_ERR("failed to parse Route body\n");
        return -2;
    }

    *_hdr = ptr;
    return 0;
}
Esempio n. 20
0
/*
 * Find last route in the last Route header field,
 * if there was a previous route in the last Route header
 * field, it will be saved in _p parameter
 */
static inline int find_rem_target(struct sip_msg* _m, struct hdr_field** _h, rr_t** _l, rr_t** _p)
{
	struct hdr_field* ptr, *last;

	if (parse_headers(_m, HDR_EOH_F, 0) == -1) {
		LOG(L_ERR, "find_rem_target: Error while parsing message header\n");
		return -1;
	}

	ptr = _m->route;
	last = 0;

	while(ptr) {
		if (ptr->type == HDR_ROUTE_T) last = ptr;
		ptr = ptr->next;
	}

	if (last) {
		if (parse_rr(last) < 0) {
			LOG(L_ERR, "find_rem_target: Error while parsing last Route HF\n");
			return -2;
		}

		*_h = last;
		*_p = 0;
		*_l = (rr_t*)last->parsed;
		while ((*_l)->next) {
			*_p = *_l;
			*_l = (*_l)->next;
		}
		return 0;
	} else {
		LOG(L_ERR, "find_rem_target: Can't find last Route HF\n");
		return 1;
	}
}
Esempio n. 21
0
/*!
 * \brief Find last route in the last Route header field
 *
 * Find last route in the last Route header field, if there was a previous
 * route in the last Route header field, it will be saved in _p parameter
 * \param _m SIP message
 * \param _h SIP header field
 * \param _l Route & Record-Route header field body
 * \param _p Route & Record-Route header field body
 * \return negative on failure, 0 on success
 */
static inline int find_rem_target(struct sip_msg* _m, struct hdr_field** _h, rr_t** _l, rr_t** _p)
{
    struct hdr_field* ptr, *last;

    if (parse_headers(_m, HDR_EOH_F, 0) == -1) {
        LM_ERR("failed to parse message header\n");
        return -1;
    }

    ptr = _m->route;
    last = 0;

    while(ptr) {
        if (ptr->type == HDR_ROUTE_T) last = ptr;
        ptr = ptr->next;
    }

    if (last) {
        if (parse_rr(last) < 0) {
            LM_ERR("failed to parse last Route HF\n");
            return -2;
        }

        *_p = 0;
        *_l = (rr_t*)last->parsed;
        *_h = last;
        while ((*_l)->next) {
            *_p = *_l;
            *_l = (*_l)->next;
        }
        return 0;
    } else {
        LM_ERR("search for last Route HF failed\n");
        return 1;
    }
}
Esempio n. 22
0
static int l_siplua_getRoute(lua_State *L)
{
  struct sipapi_object *o;
  rr_t *rt;
  str uri;
  struct sip_uri puri;
  int n = 1;

  o = luaL_checkudata(L, 1, "siplua.api");
  if (parse_headers(o->msg, HDR_ROUTE_F, 0) == -1)
    return luaL_error(L, "failed to parse headers");
  if (!o->msg->route)
    {
      lua_pushnil(L);
      return 1;
    }
  if (parse_rr(o->msg->route) < 0)
    return luaL_error(L, "failed to parse route HF");
  lua_newtable(L);
  for (rt = (rr_t *)o->msg->route->parsed; rt; rt = rt->next )
    {
      uri = rt->nameaddr.uri;
      lua_pushinteger(L, n++);
      lua_newtable(L);
      lua_pushliteral(L, "uri");
      lua_pushlstring(L, uri.s, uri.len);
      lua_rawset(L, -3);
      if (parse_uri(uri.s, uri.len, &puri) < 0)
	{
	  if (n == 1)
	    return luaL_error(L, "failed to parse the first route URI");
	  continue;
	}
      lua_pushliteral(L, "user");
      lua_pushlstring(L, puri.user.s, puri.user.len);
      lua_rawset(L, -3);
      lua_pushliteral(L, "host");
      lua_pushlstring(L, puri.host.s, puri.host.len);
      lua_rawset(L, -3);
      lua_pushliteral(L, "port");
      lua_pushinteger(L, puri.port_no);
      lua_rawset(L, -3);
      lua_pushliteral(L, "params");
      lua_pushlstring(L, puri.params.s, puri.params.len);
      lua_rawset(L, -3);
      lua_pushliteral(L, "lr");
      lua_pushlstring(L, puri.lr.s, puri.lr.len);
      lua_rawset(L, -3);
      lua_pushliteral(L, "lr_val");
      lua_pushlstring(L, puri.lr_val.s, puri.lr_val.len);
      lua_rawset(L, -3);
      lua_pushliteral(L, "r2");
      lua_pushlstring(L, puri.r2.s, puri.r2.len);
      lua_rawset(L, -3);
      lua_pushliteral(L, "r2_val");
      lua_pushlstring(L, puri.r2_val.s, puri.r2_val.len);
      lua_rawset(L, -3);
      lua_pushliteral(L, "is_myself");
      if (check_self(&puri.host, puri.port_no ? puri.port_no : SIP_PORT, 0) >= 0)
	lua_pushboolean(L, 1);
      else
	lua_pushboolean(L, 0);
      lua_rawset(L, -3);
      lua_rawset(L, -3);
    }
  return 1;
}
Esempio n. 23
0
int tps_pack_request(sip_msg_t *msg, tps_data_t *ptsd)
{
	hdr_field_t *hdr;
	via_body_t *via;
	rr_t *rr;
	int i;
	int vlen;

	if(ptsd->cp==NULL) {
		ptsd->cp = ptsd->cbuf;
	}
	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++;
			vlen = tps_skip_rw(via->name.s, via->bsize);
			if(ptsd->cp + vlen + 2 >= ptsd->cbuf + TPS_DATA_SIZE) {
				LM_ERR("no more spage to pack via headers\n");
				return -1;
			}
			if(i>1) {
				*ptsd->cp = ',';
				ptsd->cp++;
				if(i>2) {
					ptsd->x_via2.len++;
				}
			}
			memcpy(ptsd->cp, via->name.s, vlen);
			if(i==1) {
				ptsd->x_via1.s = ptsd->cp;
				ptsd->x_via1.len = vlen;
				if(via->branch!=NULL) {
					ptsd->x_vbranch1.s = ptsd->x_via1.s + (via->branch->value.s - via->name.s);
					ptsd->x_vbranch1.len = via->branch->value.len;
				}
			} else {
				if(i==2) {
					ptsd->x_via2.s = ptsd->cp;
				}
				ptsd->x_via2.len += vlen;
			}
			ptsd->cp += vlen;
		}
	}
	LM_DBG("compacted headers - x_via1: [%.*s](%d) - x_via2: [%.*s](%d)"
			" - x_vbranch1: [%.*s](%d)\n",
			ptsd->x_via1.len, ZSW(ptsd->x_via1.s), ptsd->x_via1.len,
			ptsd->x_via2.len, ZSW(ptsd->x_via2.s), ptsd->x_via2.len,
			ptsd->x_vbranch1.len, ZSW(ptsd->x_vbranch1.s), ptsd->x_vbranch1.len);

	i = 0;
	ptsd->a_rr.len = 0;
	for(hdr=msg->record_route; hdr; hdr=next_sibling_hdr(hdr)) {
		if (parse_rr(hdr) < 0) {
			LM_ERR("failed to parse RR\n");
			return -1;
		}

		for(rr =(rr_t*)hdr->parsed; rr; rr=rr->next) {
			i++;
			if(ptsd->cp + rr->nameaddr.uri.len + 4 >= ptsd->cbuf + TPS_DATA_SIZE) {
				LM_ERR("no more spage to pack rr headers\n");
				return -1;
			}
			if(i>1) {
				*ptsd->cp = ',';
				ptsd->cp++;
				ptsd->a_rr.len++;
			}
			*ptsd->cp = '<';
			if(i==1) {
				ptsd->a_rr.s = ptsd->cp;
			}
			ptsd->cp++;
			ptsd->a_rr.len++;

			memcpy(ptsd->cp, rr->nameaddr.uri.s, rr->nameaddr.uri.len);
			if(i==1) {
				ptsd->bs_contact.s = ptsd->cp;
				ptsd->bs_contact.len = rr->nameaddr.uri.len;
				if(strnstr(ptsd->bs_contact.s, ";r2=on",
							ptsd->bs_contact.len)==NULL) {
					LM_DBG("single record routing by proxy\n");
					ptsd->as_contact.s = ptsd->cp;
					ptsd->as_contact.len = rr->nameaddr.uri.len;
				}
			} else {
				if(i==2 && ptsd->as_contact.len==0) {
					LM_DBG("double record routing by proxy\n");
					ptsd->as_contact.s = ptsd->cp;
					ptsd->as_contact.len = rr->nameaddr.uri.len;
				}
			}
			ptsd->a_rr.len += rr->nameaddr.uri.len;
			ptsd->cp += rr->nameaddr.uri.len;
			*ptsd->cp = '>';
			ptsd->cp++;
			ptsd->a_rr.len++;
		}

	}
	LM_DBG("compacted headers - a_rr: [%.*s](%d) - b_rr: [%.*s](%d)\n",
			ptsd->a_rr.len, ZSW(ptsd->a_rr.s), ptsd->a_rr.len,
			ptsd->b_rr.len, ZSW(ptsd->b_rr.s), ptsd->b_rr.len);
	LM_DBG("compacted headers - as_contact: [%.*s](%d) - bs_contact: [%.*s](%d)\n",
			ptsd->as_contact.len, ZSW(ptsd->as_contact.s), ptsd->as_contact.len,
			ptsd->bs_contact.len, ZSW(ptsd->bs_contact.s), ptsd->bs_contact.len);
	return 0;
}
Esempio n. 24
0
/**
 * Returns the content of the Service-Route header.
 * data vector is pkg_alloced and should be later freed
 * inside values are not duplicated
 * @param msg - the SIP message
 * @param size - size of the returned vector, filled with the result
 * @param is_shm - msg from shared memory
 * @returns - the str vector of uris
 */
str* cscf_get_service_route(struct sip_msg *msg, int *size, int is_shm) {
	struct hdr_field *h;
	rr_t *r, *r2;
	str *x = 0;
	int k;
	if (!size)
		return 0;

	*size = 0;

	if (!msg)
		return 0;
	if (parse_headers(msg, HDR_EOH_F, 0) < 0) {
		LM_ERR("error parsing headers\n");
		return 0;
	}
	h = msg->headers;
	while (h) {
		if (h->name.len == 13
				&& strncasecmp(h->name.s, "Service-Route", 13) == 0) {
			if (parse_rr(h) < 0) {
				LM_ERR("Error parsing as Route header\n");
				continue;
			}
			r = (rr_t*) h->parsed;
			h->type = HDR_ROUTE_T;
			r2 = r;
			k = 0;
			while (r2) {
				k++;
				r2 = r2->next;
			}
			if (!k) {
				LM_DBG("No items in this Service-Route\n");
				continue;
			}
			x = pkg_realloc(x,(*size+k)*sizeof(str));
			if (!x) {
				LM_ERR("Error our of pkg memory");
				return 0;
			}
			r2 = r;
			while (r2) {
				x[*size] = r2->nameaddr.uri;
				(*size) = (*size) + 1;
				r2 = r2->next;
			}
		}
		h = h->next;
	}
	if (is_shm) {
		h = msg->headers;
		while (h) {
			if (h->name.len == 13
					&& strncasecmp(h->name.s, "Service-Route", 13) == 0) {
				r = (rr_t*) h->parsed;
				h->parsed = 0;
				free_rr(&r);
			}
			h = h->next;
		}
	}

	return x;
}
Esempio n. 25
0
/**
 * Extract route set from the message (out of Record-Route, if reply, OR
 * Route, if request).
 * The route set is returned into the "UAC-format" (keep order for Rs, reverse
 * RRs).
 */
static inline int get_uac_rs(sip_msg_t *msg, int is_req, struct rte **rtset)
{
	struct hdr_field* ptr;
	rr_t *p, *new_p;
	struct rte *t, *head, *old_head;

	head = 0;
	for (ptr = is_req ? msg->route : msg->record_route; ptr; ptr = ptr->next) {
		switch (ptr->type) {
			case HDR_RECORDROUTE_T:
				if (is_req)
					continue;
				break;
			case HDR_ROUTE_T:
				if (! is_req)
					continue;
				break;
			default:
				continue;
		}
		if (parse_rr(ptr) < 0) {
			LM_ERR("failed to parse Record-/Route HF (%d).\n", ptr->type);
			goto err;
		}

		p = (rr_t*)ptr->parsed;
		while(p) {
			if (! (t = pkg_malloc(sizeof(struct rte)))) {
				LM_ERR("out of pkg mem (asked for: %d).\n",
						(int)sizeof(struct rte));
				goto err;
			}
			if (is_req) {
				/* in case of requests, the sip_msg structure is free'd before
				 * rte list is evaluated => must do a copy of it */
				if (duplicate_rr(&new_p, p) < 0) {
					pkg_free(t);
					LM_ERR("failed to duplicate RR");
					goto err;
				}
				t->ptr = new_p;
			} else {
				t->ptr = p;
			}
			t->free_rr = is_req;
			t->next = head;
			head = t;
			p = p->next;
		}
	}

	if (is_req) {
		/* harvesting the R/RR HF above inserts at head, which suites RRs (as
		 * they must be reversed, anyway), but not Rs => reverse once more */
		old_head = head;
		head = 0;
		while (old_head) {
			t = old_head;
			old_head = old_head->next;
			t->next = head;
			head = t;
		}
	}

	*rtset = head;
	return 0;
err:
	free_rte_list(head);
	return -1;
}
Esempio n. 26
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;
}
Esempio n. 27
0
/* Actions are composed as follows:
 * (the action length and type as always= 5 bytes)
 *
 * TODO performance speedup: instead of using
 * dynamically allocated memory for headers,body,totag,reason and my_msg
 * use static buffers.
 *
 */
int ac_sl_msg(as_p the_as,unsigned char processor_id,unsigned int flags,char *action,int len)
{
   struct sip_msg *my_msg;
   str *uri;
   struct proxy_l *proxy;
   rr_t *my_route;
   int k,retval;
   //enum sip_protos proto;

   my_msg=NULL;
   k=0;

   proxy=0;

   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_REQUEST)
      LM_DBG("forwarding request:\"%.*s\" statelessly \n",my_msg->first_line.u.request.method.len+1+\
	    my_msg->first_line.u.request.uri.len,my_msg->first_line.u.request.method.s);
   else
      LM_DBG("forwarding reply:\"%.*s\" statelessly \n",my_msg->first_line.u.reply.status.len+1+\
	    my_msg->first_line.u.reply.reason.len,my_msg->first_line.u.reply.status.s);

   if (my_msg->route) {
      if (parse_rr(my_msg->route) < 0) {
	 LM_ERR( "Error while parsing Route body\n");
	 goto error;
      }
      my_route = (rr_t*)my_msg->route->parsed;
      uri=&(my_route->nameaddr.uri);
   }else{
      uri = GET_RURI(my_msg);
   }
   set_force_socket(my_msg, grep_sock_info(&my_msg->via1->host,
                                            my_msg->via1->port,
                                            my_msg->via1->proto) );
   /* or also could be:
      my_msg->force_send_socket=the_as->binds[processor_id].bind_address;
      not sure which is better...
      */
   /*proxy=uri2proxy(uri,PROTO_NONE);
   if (proxy==0) {
      LM_ERR("unable to create proxy from URI \n");
      goto error;
   }
   proto=proxy->proto;
   */
   //TODO my_msg->recvd
   if(0>forward_sl_request(my_msg,uri,PROTO_NONE))
      goto error;
   retval=0;
   goto exit;
error:
   retval = -1;
exit:
   if(proxy){
      free_proxy(proxy);
      pkg_free(proxy);
   }
   if(my_msg){
      free_sip_msg_lite(my_msg);
      pkg_free(my_msg);
   }
   return retval;
}
Esempio n. 28
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. 29
0
/*!
 * get first RR header and print comma separated bodies in oroute
 * - order = 0 normal; order = 1 reverse
 * - nb_recs - input=skip number of rr; output=number of printed rrs
 */
int print_rr_body(struct hdr_field *iroute, str *oroute, int order,
												unsigned int * nb_recs)
{
	rr_t *p;
	int n = 0, nr=0;
	int i = 0;
	int route_len;
#define MAX_RR_HDRS	64
	static str route[MAX_RR_HDRS];
	char *cp, *start;

	if(iroute==NULL)
		return 0;

	route_len= 0;
	memset(route, 0, MAX_RR_HDRS*sizeof(str));

	while (iroute!=NULL) 
	{
		if (parse_rr(iroute) < 0) 
		{
			LM_ERR("failed to parse RR\n");
			goto error;
		}

		p =(rr_t*)iroute->parsed;
		while (p)
		{
			route[n].s = p->nameaddr.name.s;
			route[n].len = p->len;
			LM_DBG("current rr is %.*s\n", route[n].len, route[n].s);

			n++;
			if(n==MAX_RR_HDRS)
			{
				LM_ERR("too many RR\n");
				goto error;
			}
			p = p->next;
		}

		iroute = next_sibling_hdr(iroute);
	}

	for(i=0;i<n;i++){
		if(!nb_recs || (nb_recs && 
		 ( (!order&& (i>=*nb_recs)) || (order && (i<=(n-*nb_recs)) )) ) )
		{
			route_len+= route[i].len;
			nr++;
		}
	
	}

	if(nb_recs)
		LM_DBG("skipping %i route records\n", *nb_recs);
	
	route_len += --nr; /* for commas */

	oroute->s=(char*)pkg_malloc(route_len);


	if(oroute->s==0)
	{
		LM_ERR("no more pkg mem\n");
		goto error;
	}
	cp = start = oroute->s;
	if(order==0)
	{
		i= (nb_recs == NULL) ? 0:*nb_recs;

		while (i<n)
		{
			memcpy(cp, route[i].s, route[i].len);
			cp += route[i].len;
			if (++i<n)
				*(cp++) = ',';
		}
	} else {
		
		i = (nb_recs == NULL) ? n-1 : (n-*nb_recs-1);
			
		while (i>=0)
		{
			memcpy(cp, route[i].s, route[i].len);
			cp += route[i].len;
			if (i-->0)
				*(cp++) = ',';
		}
	}
	oroute->len=cp - start;

	LM_DBG("out rr [%.*s]\n", oroute->len, oroute->s);
	LM_DBG("we have %i records\n", n);
	if(nb_recs != NULL)
		*nb_recs = (unsigned int)n; 

	return 0;

error:
	return -1;
}
Esempio n. 30
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;
}