Beispiel #1
0
int via_diff(struct sip_msg *req,struct sip_msg *resp)
{
   struct hdr_field *hf;
   struct via_body *vb;
   int i,j,k;

   i=j=k=0;
   /* count how many via bodies come in the response*/
   for(hf=resp->h_via1;hf;hf=next_sibling_hdr(hf)){
      if(!hf->parsed){
	 if((vb=pkg_malloc(sizeof(struct via_body)))==0){
	    LM_ERR("Out of mem in via_diff!!\n");
	    return -1;
	 }
	 memset(vb,0,sizeof(struct via_body));
	 if(parse_via(hf->body.s,hf->body.s+hf->body.len+1,vb)==0){
	    LM_ERR("Unable to parse via in via_diff!\n");
	    pkg_free(vb);
	    return -1;
	 }
	 hf->parsed=vb;
	 j=1;
      }
      for(vb=hf->parsed;vb;vb=vb->next){
	 i++;
      }
      if(j){
	 free_via_list((struct via_body*)hf->parsed);
	 hf->parsed=NULL;
	 j=0;
      }
   }
   j=0;
   /* count how many via bodies were in the orig. request*/
   for(hf=req->h_via1;hf;hf=next_sibling_hdr(hf)){
      if(!hf->parsed){
	 if((vb=pkg_malloc(sizeof(struct via_body)))==0){
	    goto error;
	 }
	 memset(vb,0,sizeof(struct via_body));
	 if(parse_via(hf->body.s,hf->body.s+hf->body.len+1,vb)==0){
	    goto error;
	 }
	 hf->parsed=vb;
	 j=1;
      }
      for(vb=hf->parsed;vb;vb=vb->next){
	 k++;
      }
      if(j){
	 free_via_list((struct via_body*)hf->parsed);
	 hf->parsed=NULL;
	 j=0;
      }
   }
   return i-k;
error:
   return -1;
}
Beispiel #2
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;
}
Beispiel #3
0
/*! \brief
 * Combines all Path HF bodies into one string.
 */
int build_path_vector(struct sip_msg *_m, str *path, str *received) {
    static char buf[MAX_PATH_SIZE];
    char *p;
    struct hdr_field *hdr;
    struct sip_uri puri;

    rr_t *route = 0;

    path->len = 0;
    path->s = 0;
    received->s = 0;
    received->len = 0;

    if (parse_headers(_m, HDR_EOH_F, 0) < 0) {
	LM_ERR("failed to parse the message\n");
	goto error;
    }

    for (hdr = _m->path, p = buf; hdr; hdr = next_sibling_hdr(hdr)) {
	/* check for max. Path length */
	if (p - buf + hdr->body.len + 1 >= MAX_PATH_SIZE) {
	    LM_ERR("Overall Path body exceeds max. length of %d\n",
		    MAX_PATH_SIZE);
	    goto error;
	}
	if (p != buf)
	    *(p++) = ',';
	memcpy(p, hdr->body.s, hdr->body.len);
	p += hdr->body.len;
    }

    if (p != buf) {
	/* check if next hop is a loose router */
	if (parse_rr_body(buf, p - buf, &route) < 0) {
	    LM_ERR("failed to parse Path body, no head found\n");
	    goto error;
	}
	if (parse_uri(route->nameaddr.uri.s, route->nameaddr.uri.len, &puri) < 0) {
	    LM_ERR("failed to parse the first Path URI\n");
	    goto error;
	}
	if (!puri.lr.s) {
	    LM_ERR("first Path URI is not a loose-router, not supported\n");
	    goto error;
	}
	free_rr(&route);
    }

    path->s = buf;
    path->len = p - buf;
    return 0;
error:
    if (route) free_rr(&route);
    return -1;
}
Beispiel #4
0
int th_mask_via(sip_msg_t *msg)
{
	hdr_field_t *hdr;
	struct via_body *via;
	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)
			{
				out.s = th_mask_encode(via->name.s, vlen, &th_via_prefix,
						&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);
				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;
}
Beispiel #5
0
/*!
 * Parse all Supported headers
 */
int parse_supported( struct sip_msg *msg)
{
	unsigned int supported;
	struct hdr_field  *hdr;
	struct option_tag_body *sb;

	/* maybe the header is already parsed! */
	if (msg->supported && msg->supported->parsed)
		return 0;

	/* parse to the end in order to get all SUPPORTED headers */
	if (parse_headers(msg,HDR_EOH_F,0)==-1 || !msg->supported)
		return -1;

	/* bad luck! :-( - we have to parse them */
	supported = 0;
	for( hdr=msg->supported ; hdr ; hdr=next_sibling_hdr(hdr)) {
		if (hdr->parsed) {
			supported |= ((struct option_tag_body*)hdr->parsed)->option_tags;
			continue;
		}

		sb = (struct option_tag_body*)pkg_malloc(sizeof(struct option_tag_body));
		if (sb == 0) {
			LM_ERR("out of pkg_memory\n");
			return -1;
		}

		parse_option_tag_body(&(hdr->body), &(sb->option_tags));
		sb->hfree = hf_free_option_tag;
		sb->option_tags_all = 0;
		hdr->parsed = (void*)sb;
		supported |= sb->option_tags;
	}

	((struct option_tag_body*)msg->supported->parsed)->option_tags_all = 
		supported;
	return 0;
}
Beispiel #6
0
/*!
 * Parse all Require headers
 */
int parse_require( struct sip_msg *msg)
{
	unsigned int require;
	struct hdr_field  *hdr;
	struct option_tag_body *rb;

	/* maybe the header is already parsed! */
	if (msg->require && msg->require->parsed)
		return 0;

	/* parse to the end in order to get all SUPPORTED headers */
	if (parse_headers(msg,HDR_EOH_F,0)==-1 || !msg->require)
		return -1;

	/* bad luck! :-( - we have to parse them */
	require = 0;
	for( hdr=msg->require ; hdr ; hdr=next_sibling_hdr(hdr)) {
		if (hdr->parsed) {
			require |= ((struct option_tag_body*)hdr->parsed)->option_tags;
			continue;
		}

		rb = (struct option_tag_body*)pkg_malloc(sizeof(struct option_tag_body));
		if (rb == 0) {
			LM_ERR("out of pkg_memory\n");
			return -1;
		}

		parse_option_tag_body(&(hdr->body), &(rb->option_tags));
		rb->hfree = hf_free_option_tag;
		rb->option_tags_all = 0;
		hdr->parsed = (void*)rb;
		require |= rb->option_tags;
	}

	((struct option_tag_body*)msg->require->parsed)->option_tags_all = 
		require;
	return 0;
}
Beispiel #7
0
/*! \brief
 * Combines all Path HF bodies into one string.
 */
int build_path_vector(struct sip_msg *_m, str *path, str *received)
{
	static char buf[MAX_PATH_BUFFER];
	char *p;
	struct hdr_field *hdr;
	struct sip_uri puri;

	rr_t *route = 0;

	path->len = 0;
	path->s = 0;
	received->s = 0;
	received->len = 0;

	if(parse_headers(_m, HDR_EOH_F, 0) < 0) {
		LM_ERR("failed to parse the message\n");
		goto error;
	}

	for( hdr=_m->path,p=buf ; hdr ; hdr = next_sibling_hdr(hdr)) {
		/* check for max. Path length */
		if( p-buf+hdr->body.len+1 >= MAX_PATH_BUFFER) {
			LM_ERR("Overall Path body exceeds max. length of %d - trying to add header [%.*s] and already have [%.*s]\n",
					MAX_PATH_BUFFER,
                                        hdr->body.len, hdr->body.s,
                                        (int)(p-buf), buf);
			goto error;
		}
		if(p!=buf)
			*(p++) = ',';
		memcpy( p, hdr->body.s, hdr->body.len);
		p +=  hdr->body.len;
	}

	if (p!=buf) {
		/* check if next hop is a loose router */
		if (parse_rr_body( buf, p-buf, &route) < 0) {
			LM_ERR("failed to parse Path body, no head found\n");
			goto error;
		}
		if (parse_uri(route->nameaddr.uri.s,route->nameaddr.uri.len,&puri)<0){
			LM_ERR("failed to parse the first Path URI\n");
			goto error;
		}
		if (!puri.lr.s) {
			LM_ERR("first Path URI is not a loose-router, not supported\n");
			goto error;
		}
		if (path_use_params) {
			param_hooks_t hooks;
			param_t *params;

			if (parse_params(&(puri.params),CLASS_CONTACT,&hooks,&params)!=0){
				LM_ERR("failed to parse parameters of first hop\n");
				goto error;
			}
			if (hooks.contact.received)
				*received = hooks.contact.received->body;
			/*for (;params; params = params->next) {
				if (params->type == P_RECEIVED) {
					*received = hooks.contact.received->body;
					break;
				}
			}*/
			free_params(params);
		}
		free_rr(&route);
	}

	path->s = buf;
	path->len = p-buf;
	return 0;
error:
	if(route) free_rr(&route);
	return -1;
}
Beispiel #8
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;
}
Beispiel #9
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;
}
Beispiel #10
0
/* Build a local request based on a previous request; main
 * customers of this function are local ACK and local CANCEL
 */
char *build_local(struct cell *Trans,unsigned int branch,
	unsigned int *len, char *method, int method_len, str *to
#ifdef CANCEL_REASON_SUPPORT
	, struct cancel_reason* reason
#endif /* CANCEL_REASON_SUPPORT */
	)
{
	char                *cancel_buf, *p, *via;
	unsigned int         via_len;
	struct hdr_field    *hdr;
	char branch_buf[MAX_BRANCH_PARAM_LEN];
	int branch_len;
	str branch_str;
	str via_id;
	struct hostport hp;
#ifdef CANCEL_REASON_SUPPORT
	int reason_len, code_len;
	struct hdr_field *reas1, *reas_last;
#endif /* CANCEL_REASON_SUPPORT */

	/* init */
	via_id.s=0;
	via_id.len=0;

	/* method, separators, version: "CANCEL sip:[email protected] SIP/2.0" */
	*len=SIP_VERSION_LEN + method_len + 2 /* spaces */ + CRLF_LEN;
	*len+=Trans->uac[branch].uri.len;

	/*via*/
	if (!t_calc_branch(Trans,  branch,
		branch_buf, &branch_len ))
		goto error;
	branch_str.s=branch_buf;
	branch_str.len=branch_len;
	set_hostport(&hp, (is_local(Trans))?0:(Trans->uas.request));
#ifdef USE_TCP
	if (!is_local(Trans) && ((Trans->uas.request->rcv.proto==PROTO_TCP)
#ifdef USE_TLS
				|| (Trans->uas.request->rcv.proto==PROTO_TLS)
#endif /* USE_TLS */
		)){
		if ((via_id.s=id_builder(Trans->uas.request,
									(unsigned int*)&via_id.len))==0){
			LM_ERR("id builder failed\n");
			/* try to continue without id */
		}
	}
#endif /* USE_TCP */
	via=via_builder(&via_len, NULL, &Trans->uac[branch].request.dst,
		&branch_str, via_id.s?&via_id:0 , &hp );

	/* via_id.s not needed anylonger => free it */
	if (via_id.s) {
		pkg_free(via_id.s);
		via_id.s=0;
		via_id.len=0;
	}

	if (!via) {
		LM_ERR("no via header got from builder\n");
		goto error;
	}
	*len+= via_len;
	/*headers*/
	*len+=Trans->from.len+Trans->callid.len+to->len+
		+Trans->cseq_n.len+1+method_len+CRLF_LEN+MAXFWD_HEADER_LEN;


	/* copy'n'paste Route headers */
	if (!is_local(Trans)) {
		for ( hdr=Trans->uas.request->headers ; hdr ; hdr=hdr->next )
			if (hdr->type==HDR_ROUTE_T)
				*len+=hdr->len;
	}

	/* User Agent */
	if (server_signature) {
		*len += user_agent_hdr.len + CRLF_LEN;
	}
	/* Content Length, EoM */
	*len+=CONTENT_LENGTH_LEN+1 + CRLF_LEN;
#ifdef CANCEL_REASON_SUPPORT
	reason_len = 0;
	reas1 = 0;
	reas_last = 0;
	/* compute reason size (if no reason or disabled => reason_len == 0)*/
	if (reason && reason->cause != CANCEL_REAS_UNKNOWN){
		if (likely(reason->cause > 0 &&
					cfg_get(tm, tm_cfg, local_cancel_reason))){
			/* Reason: SIP;cause=<reason->cause>[;text=<reason->u.text.s>] */
			reason_len = REASON_PREFIX_LEN + USHORT2SBUF_MAX_LEN +
				(reason->u.text.s?
					REASON_TEXT_LEN + 1 + reason->u.text.len + 1 : 0) +
				CRLF_LEN;
		} else if (likely(reason->cause == CANCEL_REAS_PACKED_HDRS &&
					!(Trans->flags & T_NO_E2E_CANCEL_REASON))) {
			reason_len = reason->u.packed_hdrs.len;
		} else if (reason->cause == CANCEL_REAS_RCVD_CANCEL &&
					reason->u.e2e_cancel &&
					!(Trans->flags & T_NO_E2E_CANCEL_REASON)) {
			/* parse the entire cancel, to get all the Reason headers */
			if(parse_headers(reason->u.e2e_cancel, HDR_EOH_F, 0)<0) {
				LM_WARN("failed to parse headers\n");
			}
			for(hdr=get_hdr(reason->u.e2e_cancel, HDR_REASON_T), reas1=hdr;
					hdr; hdr=next_sibling_hdr(hdr)) {
				/* hdr->len includes CRLF */
				reason_len += hdr->len;
				reas_last=hdr;
			}
		} else if (unlikely(reason->cause < CANCEL_REAS_MIN))
			LM_BUG("unhandled reason cause %d\n", reason->cause);
	}
	*len+= reason_len;
#endif /* CANCEL_REASON_SUPPORT */
	*len+= CRLF_LEN; /* end of msg. */

	cancel_buf=shm_malloc( *len+1 );
	if (!cancel_buf) {
		LM_ERR("cannot allocate memory\n");
		goto error01;
	}
	p = cancel_buf;

	append_str( p, method, method_len );
	append_str( p, " ", 1 );
	append_str( p, Trans->uac[branch].uri.s, Trans->uac[branch].uri.len);
	append_str( p, " " SIP_VERSION CRLF, 1+SIP_VERSION_LEN+CRLF_LEN );

	/* insert our via */
	append_str(p,via,via_len);

	/*other headers*/
	append_str( p, Trans->from.s, Trans->from.len );
	append_str( p, Trans->callid.s, Trans->callid.len );
	append_str( p, to->s, to->len );

	append_str( p, Trans->cseq_n.s, Trans->cseq_n.len );
	append_str( p, " ", 1 );
	append_str( p, method, method_len );
	append_str( p, CRLF, CRLF_LEN );
	append_str( p, MAXFWD_HEADER, MAXFWD_HEADER_LEN );

	if (!is_local(Trans))  {
		for ( hdr=Trans->uas.request->headers ; hdr ; hdr=hdr->next )
			if(hdr->type==HDR_ROUTE_T) {
				append_str(p, hdr->name.s, hdr->len );
			}
	}

	/* User Agent header */
	if (server_signature) {
		append_str(p, user_agent_hdr.s, user_agent_hdr.len );
		append_str(p, CRLF, CRLF_LEN );
	}
	/* Content Length */
	append_str(p, CONTENT_LENGTH "0" CRLF, CONTENT_LENGTH_LEN + 1 + CRLF_LEN);
#ifdef CANCEL_REASON_SUPPORT
	/* add reason if needed */
	if (reason_len) {
		if (likely(reason->cause > 0)) {
			append_str(p, REASON_PREFIX, REASON_PREFIX_LEN);
			code_len=ushort2sbuf(reason->cause, p,
									*len-(int)(p-cancel_buf));
			if (unlikely(code_len==0))
				LM_BUG("not enough space to write reason code");
			p+=code_len;
			if (reason->u.text.s){
				append_str(p, REASON_TEXT, REASON_TEXT_LEN);
				*p='"'; p++;
				append_str(p, reason->u.text.s, reason->u.text.len);
				*p='"'; p++;
			}
			append_str(p, CRLF, CRLF_LEN);
		} else if (likely(reason->cause == CANCEL_REAS_PACKED_HDRS)) {
			append_str(p, reason->u.packed_hdrs.s, reason->u.packed_hdrs.len);
		} else if (reason->cause == CANCEL_REAS_RCVD_CANCEL) {
			for(hdr=reas1; hdr; hdr=next_sibling_hdr(hdr)) {
				/* hdr->len includes CRLF */
				append_str(p, hdr->name.s, hdr->len);
				if (likely(hdr==reas_last))
					break;
			}
		}
	}
#endif /* CANCEL_REASON_SUPPORT */
	append_str(p, CRLF, CRLF_LEN); /* msg. end */
	*p=0;

	pkg_free(via);
	return cancel_buf;
error01:
	pkg_free(via);
error:
	return NULL;
}
Beispiel #11
0
/* Re-parsing version of build_local() function:
 * it builds a local CANCEL or ACK (for non-200 response) request based on
 * the previous INVITE which was sent out.
 *
 * Can not be used to build other type of requests!
 */
char *build_local_reparse(struct cell *Trans,unsigned int branch,
	unsigned int *len, char *method, int method_len, str *to
#ifdef CANCEL_REASON_SUPPORT
	, struct cancel_reason *reason
#endif /* CANCEL_REASON_SUPPORT */
	)
{
	char	*invite_buf, *invite_buf_end;
	char	*cancel_buf;
	char	*s, *s1, *d;	/* source and destination buffers */
	short	invite_len;
	enum _hdr_types_t	hf_type;
	int	first_via, to_len;
	int cancel_buf_len;
#ifdef CANCEL_REASON_SUPPORT
	int reason_len, code_len;
	struct hdr_field *reas1, *reas_last, *hdr;
#endif /* CANCEL_REASON_SUPPORT */
	int hadded = 0;
	sr_cfgenv_t *cenv = NULL;

	invite_buf = Trans->uac[branch].request.buffer;
	invite_len = Trans->uac[branch].request.buffer_len;

	if (!invite_buf || !invite_len) {
		LM_ERR("INVITE is missing\n");
		goto error;
	}
	if ((*invite_buf != 'I') && (*invite_buf != 'i')) {
		LM_ERR("trying to build with local reparse"
					" for a non-INVITE request?\n");
		goto error;
	}

#ifdef CANCEL_REASON_SUPPORT
	reason_len = 0;
	reas1 = 0;
	reas_last = 0;
	/* compute reason size (if no reason or disabled => reason_len == 0)*/
	if (reason && reason->cause != CANCEL_REAS_UNKNOWN){
		if (likely(reason->cause > 0 &&
					cfg_get(tm, tm_cfg, local_cancel_reason))){
			/* Reason: SIP;cause=<reason->cause>[;text=<reason->u.text.s>] */
			reason_len = REASON_PREFIX_LEN + USHORT2SBUF_MAX_LEN +
				(reason->u.text.s?
					REASON_TEXT_LEN + 1 + reason->u.text.len + 1 : 0) +
				CRLF_LEN;
		} else if (likely(reason->cause == CANCEL_REAS_PACKED_HDRS &&
					!(Trans->flags & T_NO_E2E_CANCEL_REASON))) {
			reason_len = reason->u.packed_hdrs.len;
		} else if (reason->cause == CANCEL_REAS_RCVD_CANCEL &&
					reason->u.e2e_cancel &&
					!(Trans->flags & T_NO_E2E_CANCEL_REASON)) {
			/* parse the entire cancel, to get all the Reason headers */
			if(parse_headers(reason->u.e2e_cancel, HDR_EOH_F, 0)<0) {
				LM_WARN("failed to parse headers\n");
			}
			for(hdr=get_hdr(reason->u.e2e_cancel, HDR_REASON_T), reas1=hdr;
					hdr; hdr=next_sibling_hdr(hdr)) {
				/* hdr->len includes CRLF */
				reason_len += hdr->len;
				reas_last=hdr;
			}
		} else if (unlikely(reason->cause < CANCEL_REAS_MIN))
			LM_BUG("unhandled reason cause %d\n", reason->cause);
	}
#endif /* CANCEL_REASON_SUPPORT */

	invite_buf_end = invite_buf + invite_len;
	s = invite_buf;

	/* Allocate memory for the new message.
	The new request will be smaller than the INVITE, so the same size is enough.
	I just extend it with the length of new To HF to be sure.
	Ugly, but we avoid lots of checks and memory allocations this way */
	to_len = to ? to->len : 0;
#ifdef CANCEL_REASON_SUPPORT
	cancel_buf_len = invite_len + to_len + reason_len;
#else
	cancel_buf_len = invite_len + to_len;
#endif /* CANCEL_REASON_SUPPORT */
	cancel_buf = shm_malloc(sizeof(char)*cancel_buf_len);
	if (!cancel_buf)
	{
		LM_ERR("cannot allocate shared memory\n");
		goto error;
	}
	d = cancel_buf;

	/* method name + space */
	append_str(d, method, method_len);
	*d = ' ';
	d++;
	/* skip "INVITE " and copy the rest of the line including CRLF */
	s += 7;
	s1 = s;
	s = eat_line(s, invite_buf_end - s);
	append_str(d, s1, s - s1);

	cenv = sr_cfgenv_get();

	/* check every header field name,
	we must exclude and modify some of the headers */
	first_via = 1;
	while (s < invite_buf_end) {
		s1 = s;
		if ((*s == '\n') || (*s == '\r')) {
			/* end of SIP msg */
			hf_type = HDR_EOH_T;
		} else {
			/* parse HF name */
			s = lw_get_hf_name(s, invite_buf_end,
						&hf_type);
		}

		switch(hf_type) {
			case HDR_CSEQ_T:
				/* find the method name and replace it */
				while ((s < invite_buf_end)
					&& ((*s == ':') || (*s == ' ') || (*s == '\t') ||
						((*s >= '0') && (*s <= '9')))
					) s++;
				append_str(d, s1, s - s1);
				append_str(d, method, method_len);
				append_str(d, CRLF, CRLF_LEN);
				s = lw_next_line(s, invite_buf_end);
				break;

			case HDR_VIA_T:
				s = lw_next_line(s, invite_buf_end);
				if (first_via) {
					/* copy hf */
					append_str(d, s1, s - s1);
					first_via = 0;
				} /* else skip this line, we need olny the first via */
				break;

			case HDR_TO_T:
				if (to_len == 0) {
					/* there is no To tag required, just copy paste
					 * the header */
					s = lw_next_line(s, invite_buf_end);
					append_str(d, s1, s - s1);
				} else {
					/* use the given To HF instead of the original one */
					append_str(d, to->s, to->len);
					/* move the pointer to the next line */
					s = lw_next_line(s, invite_buf_end);
				}
				break;

			case HDR_FROM_T:
			case HDR_CALLID_T:
			case HDR_ROUTE_T:
			case HDR_MAXFORWARDS_T:
				/* copy hf */
				s = lw_next_line(s, invite_buf_end);
				append_str(d, s1, s - s1);
				break;

			case HDR_REQUIRE_T:
			case HDR_PROXYREQUIRE_T:
				/* skip this line */
				s = lw_next_line(s, invite_buf_end);
				break;

			case HDR_CONTENTLENGTH_T:
				/* copy hf name with 0 value */
				append_str(d, s1, s - s1);
				append_str(d, ": 0" CRLF, 3 + CRLF_LEN);
				/* move the pointer to the next line */
				s = lw_next_line(s, invite_buf_end);
				break;

			case HDR_EOH_T:
				/* end of SIP message found */
#ifdef CANCEL_REASON_SUPPORT
				/* add reason if needed */
				if (reason_len) {
					/* if reason_len !=0, no need for any reason enabled
					 * checks */
					if (likely(reason->cause > 0)) {
						append_str(d, REASON_PREFIX, REASON_PREFIX_LEN);
						code_len=ushort2sbuf(reason->cause, d,
										cancel_buf_len-(int)(d-cancel_buf));
						if (unlikely(code_len==0))
							LM_BUG("not enough space to write reason code");
						d+=code_len;
						if (reason->u.text.s){
							append_str(d, REASON_TEXT, REASON_TEXT_LEN);
							*d='"'; d++;
							append_str(d, reason->u.text.s,
											reason->u.text.len);
							*d='"'; d++;
						}
						append_str(d, CRLF, CRLF_LEN);
					} else if (likely(reason->cause ==
										CANCEL_REAS_PACKED_HDRS)) {
							append_str(d, reason->u.packed_hdrs.s,
											reason->u.packed_hdrs.len);
					} else if (reason->cause == CANCEL_REAS_RCVD_CANCEL) {
						for(hdr=reas1; hdr; hdr=next_sibling_hdr(hdr)) {
							/* hdr->len includes CRLF */
							append_str(d, hdr->name.s, hdr->len);
							if (likely(hdr==reas_last))
								break;
						}
					}
				}
#endif /* CANCEL_REASON_SUPPORT */
				/* final (end-of-headers) CRLF */
				append_str(d, CRLF, CRLF_LEN);
				*len = d - cancel_buf;
				/* LOG(L_DBG, "DBG: build_local: %.*s\n", *len, cancel_buf); */
				return cancel_buf;

			default:
				s = lw_next_line(s, invite_buf_end);
				hadded = 0;

				/* uac auth headers */
				if(Trans->uas.request &&
						(Trans->uas.request->msg_flags & FL_UAC_AUTH)) {
					if(s1 + cenv->uac_cseq_auth.len + 2 < invite_buf_end) {
						if(s1[cenv->uac_cseq_auth.len]==':'
								&& strncmp(s1, cenv->uac_cseq_auth.s,
									cenv->uac_cseq_auth.len)==0) {
							hadded = 1;
							append_str(d, s1, s - s1);
						} else if(s1[cenv->uac_cseq_refresh.len]==':'
								&& strncmp(s1, cenv->uac_cseq_refresh.s,
									cenv->uac_cseq_refresh.len)==0) {
							hadded = 1;
							append_str(d, s1, s - s1);
						}
					}
				}

				if(likely(hadded==0)) {
					if (cfg_get(tm, tm_cfg, ac_extra_hdrs).len
							&& (s1 + cfg_get(tm, tm_cfg, ac_extra_hdrs).len < invite_buf_end)
							&& (strncasecmp(s1,
									cfg_get(tm, tm_cfg, ac_extra_hdrs).s,
									cfg_get(tm, tm_cfg, ac_extra_hdrs).len) == 0)) {
						append_str(d, s1, s - s1);
					}
				}
				break;
		}
	}

	/* HDR_EOH_T was not found in the buffer, the message is corrupt */
	LM_ERR("HDR_EOH_T was not found\n");

	shm_free(cancel_buf);
error:
	LM_ERR("cannot build %.*s request\n", method_len, method);
	return NULL;

}
Beispiel #12
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;
}
Beispiel #13
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;
}
Beispiel #14
0
/*
 * Find credentials with given realm in a SIP message header
 */
int find_credentials(struct sip_msg* msg, str* realm,
		hdr_types_t hftype, struct hdr_field** hdr)
{
	struct hdr_field** hook, *ptr;
	hdr_flags_t hdr_flags;
	int res;
	str* r;

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

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

	ptr = *hook;

	/*
	 * Iterate through the credentials in the message and
	 * find credentials with given realm
	 */
	while(ptr) {
		res = parse_credentials(ptr);
		if (res < 0) {
			LM_ERR("error while parsing credentials\n");
			return (res == -1) ? -2 : -3;
		} else if (res == 0) {
			r = &(((auth_body_t*)(ptr->parsed))->digest.realm);

			if (r->len == realm->len) {
				if (!strncasecmp(realm->s, r->s, r->len)) {
					*hdr = ptr;
					return 0;
				}
			}
		}

		if (parse_headers(msg, hdr_flags, 1) == -1) {
			LM_ERR("error while parsing headers\n");
			return -4;
		} else {
			ptr = next_sibling_hdr(ptr);
			if (!ptr)
				break;
		}
	}

	/*
	 * Credentials with given realm not found
	 */
	return 1;
}
Beispiel #15
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)
			{
				/* Skip if route is not encoded */
				if (th_uri_prefix_checks
						&& ((rr->nameaddr.uri.len<th_uri_prefix.len) ||
						(strncasecmp(rr->nameaddr.uri.s,th_uri_prefix.s,
									th_uri_prefix.len)!=0)))
				{
					LM_DBG("rr %d is not encoded: [%.*s] - missing prefix\n", i,
							rr->nameaddr.uri.len, rr->nameaddr.uri.s);
					rr = rr->next;
					continue;
				}

				if(th_get_uri_param_value(&rr->nameaddr.uri, &th_uparam_name,
							&eval)<0 || eval.len<=0)
				{
					LM_DBG("rr %d is not encoded: [%.*s] - missing param\n", i,
							rr->nameaddr.uri.len, rr->nameaddr.uri.s);
					rr = rr->next;
					continue;
				}

				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;
}
Beispiel #16
0
/*! \brief
 * Combines all Path HF bodies into one string.
 */
int build_path_vector(struct sip_msg *_m, str *path, str *received)
{
	static char buf[MAX_PATH_SIZE];
	static char uri_buf[MAX_URI_SIZE];
	static str uri_str;
	char *p;
	struct hdr_field *hdr;
	struct sip_uri puri;

	rr_t *route = 0;

	path->len = 0;
	path->s = 0;
	received->s = 0;
	received->len = 0;

	if(parse_headers(_m, HDR_EOH_F, 0) < 0) {
		LM_ERR("failed to parse the message\n");
		goto error;
	}

	for( hdr=_m->path,p=buf ; hdr ; hdr = next_sibling_hdr(hdr)) {
		/* check for max. Path length */
		if( p-buf+hdr->body.len+1 >= MAX_PATH_SIZE) {
			LM_ERR("Overall Path body exceeds max. length of %d\n",
					MAX_PATH_SIZE);
			goto error;
		}
		if(p!=buf)
			*(p++) = ',';
		memcpy( p, hdr->body.s, hdr->body.len);
		p +=  hdr->body.len;
	}

	if (p!=buf) {
		/* check if next hop is a loose router */
		if (parse_rr_body( buf, p-buf, &route) < 0) {
			LM_ERR("failed to parse Path body, no head found\n");
			goto error;
		}
		if (parse_uri(route->nameaddr.uri.s,route->nameaddr.uri.len,&puri)<0){
			LM_ERR("failed to parse the first Path URI\n");
			goto error;
		}
		if (!puri.lr.s) {
			LM_ERR("first Path URI is not a loose-router, not supported\n");
			goto error;
		}
		if (path_use_params) {
			param_hooks_t hooks;
			param_t *params;

			if (parse_params(&(puri.params),CLASS_CONTACT,&hooks,&params)!=0){
				LM_ERR("failed to parse parameters of first hop\n");
				goto error;
			}
			/* Not interested in param body - just the hooks */
			free_params(params);

			if (hooks.contact.received) {
				uri_str.s = uri_buf;
				uri_str.len = MAX_URI_SIZE;
				if (unescape_user(&(hooks.contact.received->body), &uri_str) < 0) {
					LM_ERR("unescaping received failed\n");
					goto error;
				}
				*received = uri_str;
				LM_DBG("received is <%.*s>\n", received->len, received->s);
			}
		}
		free_rr(&route);
	}

	path->s = buf;
	path->len = p-buf;
	LM_DBG("path is <%.*s>\n", path->len, path->s);
	return 0;
error:
	if(route) free_rr(&route);
	return -1;
}