parser/msg_parser.c
512dcd98
 /*
67386619
  * sip msg. header proxy parser
512dcd98
  *
c32feee5
  * Copyright (C) 2001-2003 FhG Fokus
7dd0b342
  *
07ca8c05
  * This file is part of Kamailio, a free SIP server.
7dd0b342
  *
07ca8c05
  * Kamailio is free software; you can redistribute it and/or modify
7dd0b342
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
07ca8c05
  * Kamailio is distributed in the hope that it will be useful,
7dd0b342
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
67386619
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
9e1ff448
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
1540fad1
  *
512dcd98
  */
 
14babe14
 /** Parser :: SIP Message header proxy parser.
  * @file
  * @ingroup parser
8c4ed5f0
  */
 
3ca1a53f
 /*! \defgroup parser SIP-router SIP message parser
8c4ed5f0
  * 
  * The SIP message parser
  *
  */
 
7dd0b342
 
888ca09d
 #include <string.h>
3e429f5c
 #include <stdlib.h>
d4ed4771
 #include <sys/time.h>
512dcd98
 
1540fad1
 #include "../comp_defs.h"
888ca09d
 #include "msg_parser.h"
512dcd98
 #include "parser_f.h"
3881f12c
 #include "../ut.h"
 #include "../error.h"
 #include "../dprint.h"
 #include "../data_lump_rpl.h"
 #include "../mem/mem.h"
1400b772
 #include "../error.h"
6b109fa2
 #include "../core_stats.h"
1400b772
 #include "../globals.h"
2bb60634
 #include "parse_hname2.h"
855c2e68
 #include "parse_uri.h"
ec147e2e
 #include "parse_content.h"
08739917
 #include "parse_to.h"
b861de9c
 #include "../compiler_opt.h"
2bb60634
 
03150098
 #ifdef DEBUG_DMALLOC
dda9dab1
 #include <mem/dmalloc.h>
03150098
 #endif
 
512dcd98
 
e3c29827
 #define parse_hname(_b,_e,_h) parse_hname2((_b),(_e),(_h))
512dcd98
 
c32feee5
 /* number of via's encountered */
caf80ae6
 int via_cnt;
70b2fe02
 /* global request flags */
 unsigned int global_req_flags = 0;
512dcd98
 
f8d46776
 /* returns pointer to next header line, and fill hdr_f ;
  * if at end of header returns pointer to the last crlf  (always buf)*/
f7b97e8a
 char* get_hdr_field(char* const buf, char* const end, struct hdr_field* const hdr)
f8d46776
 {
e72b5b50
 
cccdaead
 	char *tmp = 0;
f8d46776
 	char *match;
 	struct via_body *vb;
e4067ffb
 	struct cseq_body* cseq_b;
0fcc2741
 	struct to_body* to_b;
b861de9c
 	int integer, err;
 	unsigned uval;
f8d46776
 
9fc34aad
 	if(!buf) {
 		DBG("null buffer pointer\n");
 		goto error;
 	}
 
f8d46776
 	if ((*buf)=='\n' || (*buf)=='\r'){
 		/* double crlf or lflf or crcr */
 		DBG("found end of header\n");
5c28a534
 		hdr->type=HDR_EOH_T;
f8d46776
 		return buf;
 	}
512dcd98
 
f8d46776
 	tmp=parse_hname(buf, end, hdr);
5c28a534
 	if (hdr->type==HDR_ERROR_T){
f8d46776
 		LOG(L_ERR, "ERROR: get_hdr_field: bad header\n");
 		goto error;
e72b5b50
 	}
1540fad1
 
 	/* eliminate leading whitespace */
67386619
 	tmp=eat_lws_end(tmp, end);
1540fad1
 	if (tmp>=end) {
 		LOG(L_ERR, "ERROR: get_hdr_field: HF empty\n");
 		goto error;
 	}
 
 	/* if header-field well-known, parse it, find its end otherwise ;
 	 * after leaving the hdr->type switch, tmp should be set to the
 	 * next header field
 	 */
e72b5b50
 	switch(hdr->type){
5c28a534
 		case HDR_VIA_T:
caf80ae6
 			/* keep number of vias parsed -- we want to report it in
 			   replies for diagnostic purposes */
 			via_cnt++;
22d4aa5d
 			vb=pkg_malloc(sizeof(struct via_body));
e72b5b50
 			if (vb==0){
 				LOG(L_ERR, "get_hdr_field: out of memory\n");
 				goto error;
 			}
 			memset(vb,0,sizeof(struct via_body));
 			hdr->body.s=tmp;
 			tmp=parse_via(tmp, end, vb);
34af87af
 			if (vb->error==PARSE_ERROR){
e72b5b50
 				LOG(L_ERR, "ERROR: get_hdr_field: bad via\n");
7418afcf
 				free_via_list(vb);
e72b5b50
 				goto error;
 			}
 			hdr->parsed=vb;
 			vb->hdr.s=hdr->name.s;
 			vb->hdr.len=hdr->name.len;
 			hdr->body.len=tmp-hdr->body.s;
 			break;
5c28a534
 		case HDR_CSEQ_T:
22d4aa5d
 			cseq_b=pkg_malloc(sizeof(struct cseq_body));
e4067ffb
 			if (cseq_b==0){
 				LOG(L_ERR, "get_hdr_field: out of memory\n");
 				goto error;
 			}
 			memset(cseq_b, 0, sizeof(struct cseq_body));
 			hdr->body.s=tmp;
 			tmp=parse_cseq(tmp, end, cseq_b);
 			if (cseq_b->error==PARSE_ERROR){
 				LOG(L_ERR, "ERROR: get_hdr_field: bad cseq\n");
dc453ac1
 				free_cseq(cseq_b);
e4067ffb
 				goto error;
 			}
 			hdr->parsed=cseq_b;
 			hdr->body.len=tmp-hdr->body.s;
1540fad1
 			DBG("get_hdr_field: cseq <%.*s>: <%.*s> <%.*s>\n",
67386619
 					hdr->name.len, ZSW(hdr->name.s),
 					cseq_b->number.len, ZSW(cseq_b->number.s),
1540fad1
 					cseq_b->method.len, cseq_b->method.s);
e4067ffb
 			break;
5c28a534
 		case HDR_TO_T:
0fcc2741
 			to_b=pkg_malloc(sizeof(struct to_body));
 			if (to_b==0){
 				LOG(L_ERR, "get_hdr_field: out of memory\n");
 				goto error;
 			}
 			memset(to_b, 0, sizeof(struct to_body));
 			hdr->body.s=tmp;
 			tmp=parse_to(tmp, end,to_b);
 			if (to_b->error==PARSE_ERROR){
 				LOG(L_ERR, "ERROR: get_hdr_field: bad to header\n");
dc453ac1
 				free_to(to_b);
0fcc2741
 				goto error;
0eb1315e
 			}
 			hdr->parsed=to_b;
0fcc2741
 			hdr->body.len=tmp-hdr->body.s;
1540fad1
 			DBG("DEBUG: get_hdr_field: <%.*s> [%d]; uri=[%.*s] \n",
67386619
 				hdr->name.len, ZSW(hdr->name.s),
6b6f226f
 				hdr->body.len, to_b->uri.len,ZSW(to_b->uri.s));
 			DBG("DEBUG: to body [%.*s]\n",to_b->body.len,
 				ZSW(to_b->body.s));
0eb1315e
 			break;
5c28a534
 		case HDR_CONTENTLENGTH_T:
ec147e2e
 			hdr->body.s=tmp;
 			tmp=parse_content_length(tmp,end, &integer);
 			if (tmp==0){
 				LOG(L_ERR, "ERROR:get_hdr_field: bad content_length header\n");
 				goto error;
 			}
b988daef
 			hdr->parsed=(void*)(long)integer;
ec147e2e
 			hdr->body.len=tmp-hdr->body.s;
b988daef
 			DBG("DEBUG: get_hdr_body : content_length=%d\n",
 					(int)(long)hdr->parsed);
ec147e2e
 			break;
b861de9c
 		case HDR_RETRY_AFTER_T:
 			hdr->body.s=tmp;
 			tmp=parse_retry_after(tmp,end, &uval, &err);
 			if (err){
 				LOG(L_ERR, "ERROR:get_hdr_field: bad retry_after header\n");
 				goto error;
 			}
 			hdr->parsed=(void*)(unsigned long)uval;
 			hdr->body.len=tmp-hdr->body.s;
 			DBG("DEBUG: get_hdr_body : retry_after=%d\n",
 					(unsigned)(long)hdr->parsed);
 			break;
52553188
 		case HDR_IDENTITY_T:
e7317b87
 		case HDR_DATE_T:
 		case HDR_IDENTITY_INFO_T:
5c28a534
 		case HDR_SUPPORTED_T:
e696bf82
 		case HDR_REQUIRE_T:
5c28a534
 		case HDR_CONTENTTYPE_T:
 		case HDR_FROM_T:
 		case HDR_CALLID_T:
 		case HDR_CONTACT_T:
 		case HDR_ROUTE_T:
 		case HDR_RECORDROUTE_T:
 		case HDR_MAXFORWARDS_T:
 		case HDR_AUTHORIZATION_T:
 		case HDR_EXPIRES_T:
 		case HDR_PROXYAUTH_T:
 		case HDR_PROXYREQUIRE_T:
 		case HDR_UNSUPPORTED_T:
 		case HDR_ALLOW_T:
 		case HDR_EVENT_T:
 		case HDR_ACCEPT_T:
 		case HDR_ACCEPTLANGUAGE_T:
 		case HDR_ORGANIZATION_T:
 		case HDR_PRIORITY_T:
 		case HDR_SUBJECT_T:
 		case HDR_USERAGENT_T:
fbac8f84
 		case HDR_SERVER_T:
5c28a534
 		case HDR_CONTENTDISPOSITION_T:
 		case HDR_DIVERSION_T:
 		case HDR_RPID_T:
9200d410
 		case HDR_SIPIFMATCH_T:
5c28a534
 		case HDR_REFER_TO_T:
67386619
 		case HDR_SESSIONEXPIRES_T:
8a4f3a74
 		case HDR_MIN_SE_T:
48862405
 		case HDR_SUBSCRIPTION_STATE_T:
67386619
 		case HDR_ACCEPTCONTACT_T:
 		case HDR_ALLOWEVENTS_T:
 		case HDR_CONTENTENCODING_T:
 		case HDR_REFERREDBY_T:
 		case HDR_REJECTCONTACT_T:
 		case HDR_REQUESTDISPOSITION_T:
3ed13e77
 		case HDR_WWW_AUTHENTICATE_T:
 		case HDR_PROXY_AUTHENTICATE_T:
14babe14
 		case HDR_PATH_T:
 		case HDR_PRIVACY_T:
 		case HDR_PAI_T:
 		case HDR_PPI_T:
 		case HDR_REASON_T:
5c28a534
 		case HDR_OTHER_T:
e72b5b50
 			/* just skip over it */
 			hdr->body.s=tmp;
 			/* find end of header */
 			/* find lf */
 			do{
 				match=q_memchr(tmp, '\n', end-tmp);
 				if (match){
 					match++;
 				}else {
e4067ffb
 					LOG(L_ERR,
 							"ERROR: get_hdr_field: bad body for <%s>(%d)\n",
e72b5b50
 							hdr->name.s, hdr->type);
1f377e97
 					/* abort(); */
 					tmp=end;
e72b5b50
 					goto error;
 				}
25b49bb4
 				tmp=match;
e72b5b50
 			}while( match<end &&( (*match==' ')||(*match=='\t') ) );
1540fad1
 			tmp=match;
e72b5b50
 			hdr->body.len=match-hdr->body.s;
 			break;
 		default:
 			LOG(L_CRIT, "BUG: get_hdr_field: unknown header type %d\n",
 					hdr->type);
f8d46776
 			goto error;
 	}
dda9dab1
 	/* jku: if \r covered by current length, shrink it */
 	trim_r( hdr->body );
1540fad1
 	hdr->len=tmp-hdr->name.s;
f8d46776
 	return tmp;
 error:
 	DBG("get_hdr_field: error exit\n");
6b109fa2
 	STATS_BAD_MSG_HDR();
5c28a534
 	hdr->type=HDR_ERROR_T;
1540fad1
 	hdr->len=tmp-hdr->name.s;
f8d46776
 	return tmp;
 }
 
512dcd98
 
 
e72b5b50
 /* parse the headers and adds them to msg->headers and msg->to, from etc.
  * It stops when all the headers requested in flags were parsed, on error
5c28a534
  * (bad header) or end of headers
  * WARNING: parse_headers was changed to use hdr_flags_t (the flags are now
  *          different from the header types). Don't call it with a header type
  *          (HDR_xxx_T), only with header flags (HDR_xxx_F)!*/
0a6afa42
 /* note: it continues where it previously stopped and goes ahead until
    end is encountered or desired HFs are found; if you call it twice
    for the same HF which is present only once, it will fail the second
8350de45
    time; if you call it twice and the HF is found on second time too,
    it's not replaced in the well-known HF pointer but just added to
c32feee5
    header list; if you want to use a dumb convenience function which will
    give you the first occurrence of a header you are interested in,
8350de45
    look at check_transaction_quadruple
0a6afa42
 */
a8e108ec
 int parse_headers(struct sip_msg* const msg, const hdr_flags_t flags, const int next)
e72b5b50
 {
 	struct hdr_field* hf;
 	char* tmp;
 	char* rest;
 	char* end;
5c28a534
 	hdr_flags_t orig_flag;
f27f8905
 
e72b5b50
 	end=msg->buf+msg->len;
 	tmp=msg->unparsed;
67386619
 
418a2312
 	if (unlikely(next)) {
8dd85148
 		orig_flag = msg->parsed_flag;
 		msg->parsed_flag &= ~flags;
219627a2
 	}else
67386619
 		orig_flag=0;
 
418a2312
 #ifdef EXTRA_DEBUG
5c28a534
 	DBG("parse_headers: flags=%llx\n", (unsigned long long)flags);
418a2312
 #endif
e72b5b50
 	while( tmp<end && (flags & msg->parsed_flag) != flags){
b861de9c
 		prefetch_loc_r(tmp+64, 1);
22d4aa5d
 		hf=pkg_malloc(sizeof(struct hdr_field));
b861de9c
 		if (unlikely(hf==0)){
1400b772
 			ser_error=E_OUT_OF_MEM;
e72b5b50
 			LOG(L_ERR, "ERROR:parse_headers: memory allocation error\n");
 			goto error;
 		}
7f858173
 		memset(hf,0, sizeof(struct hdr_field));
5c28a534
 		hf->type=HDR_ERROR_T;
3ed13e77
 		rest=get_hdr_field(tmp, end, hf);
e72b5b50
 		switch (hf->type){
5c28a534
 			case HDR_ERROR_T:
ec538071
 				LOG(L_INFO,"ERROR: bad header field [%.*s]\n",
c0e9cb82
 					(end-tmp>20)?20:(int)(end-tmp), tmp);
e72b5b50
 				goto  error;
5c28a534
 			case HDR_EOH_T:
e72b5b50
 				msg->eoh=tmp; /* or rest?*/
5c28a534
 				msg->parsed_flag|=HDR_EOH_F;
f27f8905
 				pkg_free(hf);
e72b5b50
 				goto skip;
67386619
 			case HDR_ACCEPTCONTACT_T:
 			case HDR_ALLOWEVENTS_T:
 			case HDR_CONTENTENCODING_T:
 			case HDR_REFERREDBY_T:
 			case HDR_REJECTCONTACT_T:
 			case HDR_REQUESTDISPOSITION_T:
3ed13e77
 			case HDR_WWW_AUTHENTICATE_T:
 			case HDR_PROXY_AUTHENTICATE_T:
b861de9c
 			case HDR_RETRY_AFTER_T:
e0404857
 			case HDR_OTHER_T: /* mark the type as found/parsed*/
 				msg->parsed_flag|=HDR_T2F(hf->type);
e72b5b50
 				break;
5c28a534
 			case HDR_CALLID_T:
e72b5b50
 				if (msg->callid==0) msg->callid=hf;
5c28a534
 				msg->parsed_flag|=HDR_CALLID_F;
e72b5b50
 				break;
9200d410
 			case HDR_SIPIFMATCH_T:
 				if (msg->sipifmatch==0) msg->sipifmatch=hf;
 				msg->parsed_flag|=HDR_SIPIFMATCH_F;
 				break;
5c28a534
 			case HDR_TO_T:
e72b5b50
 				if (msg->to==0) msg->to=hf;
5c28a534
 				msg->parsed_flag|=HDR_TO_F;
e72b5b50
 				break;
5c28a534
 			case HDR_CSEQ_T:
e72b5b50
 				if (msg->cseq==0) msg->cseq=hf;
5c28a534
 				msg->parsed_flag|=HDR_CSEQ_F;
e72b5b50
 				break;
5c28a534
 			case HDR_FROM_T:
e72b5b50
 				if (msg->from==0) msg->from=hf;
5c28a534
 				msg->parsed_flag|=HDR_FROM_F;
e72b5b50
 				break;
5c28a534
 			case HDR_CONTACT_T:
e72b5b50
 				if (msg->contact==0) msg->contact=hf;
5c28a534
 				msg->parsed_flag|=HDR_CONTACT_F;
e72b5b50
 				break;
5c28a534
 			case HDR_MAXFORWARDS_T:
10febf05
 				if(msg->maxforwards==0) msg->maxforwards=hf;
5c28a534
 				msg->parsed_flag|=HDR_MAXFORWARDS_F;
10febf05
 				break;
5c28a534
 			case HDR_ROUTE_T:
7ff8b055
 				if (msg->route==0) msg->route=hf;
5c28a534
 				msg->parsed_flag|=HDR_ROUTE_F;
7ff8b055
 				break;
5c28a534
 			case HDR_RECORDROUTE_T:
f2278164
 				if (msg->record_route==0) msg->record_route = hf;
5c28a534
 				msg->parsed_flag|=HDR_RECORDROUTE_F;
f2278164
 				break;
5c28a534
 			case HDR_CONTENTTYPE_T:
33032483
 				if (msg->content_type==0) msg->content_type = hf;
5c28a534
 				msg->parsed_flag|=HDR_CONTENTTYPE_F;
33032483
 				break;
5c28a534
 			case HDR_CONTENTLENGTH_T:
33032483
 				if (msg->content_length==0) msg->content_length = hf;
5c28a534
 				msg->parsed_flag|=HDR_CONTENTLENGTH_F;
33032483
 				break;
5c28a534
 			case HDR_AUTHORIZATION_T:
ec147e2e
 				if (msg->authorization==0) msg->authorization = hf;
5c28a534
 				msg->parsed_flag|=HDR_AUTHORIZATION_F;
e3c29827
 				break;
5c28a534
 			case HDR_EXPIRES_T:
e3c29827
 				if (msg->expires==0) msg->expires = hf;
5c28a534
 				msg->parsed_flag|=HDR_EXPIRES_F;
e3c29827
 				break;
5c28a534
 			case HDR_PROXYAUTH_T:
e3c29827
 				if (msg->proxy_auth==0) msg->proxy_auth = hf;
5c28a534
 				msg->parsed_flag|=HDR_PROXYAUTH_F;
e3c29827
 				break;
5c28a534
 			case HDR_PROXYREQUIRE_T:
e3c29827
 				if (msg->proxy_require==0) msg->proxy_require = hf;
5c28a534
 				msg->parsed_flag|=HDR_PROXYREQUIRE_F;
e3c29827
 				break;
5c28a534
 			case HDR_SUPPORTED_T:
2f43c732
 				if (msg->supported==0) msg->supported=hf;
5c28a534
 				msg->parsed_flag|=HDR_SUPPORTED_F;
2f43c732
 				break;
e696bf82
 			case HDR_REQUIRE_T:
 				if (msg->require==0) msg->require=hf;
 				msg->parsed_flag|=HDR_REQUIRE_F;
 				break;
5c28a534
 			case HDR_UNSUPPORTED_T:
e3c29827
 				if (msg->unsupported==0) msg->unsupported=hf;
5c28a534
 				msg->parsed_flag|=HDR_UNSUPPORTED_F;
e3c29827
 				break;
5c28a534
 			case HDR_ALLOW_T:
e3c29827
 				if (msg->allow==0) msg->allow = hf;
5c28a534
 				msg->parsed_flag|=HDR_ALLOW_F;
e3c29827
 				break;
5c28a534
 			case HDR_EVENT_T:
0a04a986
 				if (msg->event==0) msg->event = hf;
5c28a534
 				msg->parsed_flag|=HDR_EVENT_F;
b0a2e8ef
 				break;
5c28a534
 			case HDR_ACCEPT_T:
71be0c4a
 				if (msg->accept==0) msg->accept = hf;
5c28a534
 				msg->parsed_flag|=HDR_ACCEPT_F;
71be0c4a
 				break;
5c28a534
 			case HDR_ACCEPTLANGUAGE_T:
2f43c732
 				if (msg->accept_language==0) msg->accept_language = hf;
5c28a534
 				msg->parsed_flag|=HDR_ACCEPTLANGUAGE_F;
2f43c732
 				break;
5c28a534
 			case HDR_ORGANIZATION_T:
2f43c732
 				if (msg->organization==0) msg->organization = hf;
5c28a534
 				msg->parsed_flag|=HDR_ORGANIZATION_F;
2f43c732
 				break;
5c28a534
 			case HDR_PRIORITY_T:
2f43c732
 				if (msg->priority==0) msg->priority = hf;
5c28a534
 				msg->parsed_flag|=HDR_PRIORITY_F;
2f43c732
 				break;
5c28a534
 			case HDR_SUBJECT_T:
2f43c732
 				if (msg->subject==0) msg->subject = hf;
5c28a534
 				msg->parsed_flag|=HDR_SUBJECT_F;
2f43c732
 				break;
5c28a534
 			case HDR_USERAGENT_T:
2f43c732
 				if (msg->user_agent==0) msg->user_agent = hf;
5c28a534
 				msg->parsed_flag|=HDR_USERAGENT_F;
2f43c732
 				break;
fbac8f84
 			case HDR_SERVER_T:
 				if (msg->server==0) msg->server = hf;
 				msg->parsed_flag|=HDR_SERVER_F;
 				break;
5c28a534
 			case HDR_CONTENTDISPOSITION_T:
2f43c732
 				if (msg->content_disposition==0) msg->content_disposition = hf;
5c28a534
 				msg->parsed_flag|=HDR_CONTENTDISPOSITION_F;
6a2b0dec
 				break;
5c28a534
 			case HDR_DIVERSION_T:
dccbcda9
 				if (msg->diversion==0) msg->diversion = hf;
5c28a534
 				msg->parsed_flag|=HDR_DIVERSION_F;
dccbcda9
 				break;
5c28a534
 			case HDR_RPID_T:
dccbcda9
 				if (msg->rpid==0) msg->rpid = hf;
5c28a534
 				msg->parsed_flag|=HDR_RPID_F;
dccbcda9
 				break;
5c28a534
 			case HDR_REFER_TO_T:
8b482f1a
 				if (msg->refer_to==0) msg->refer_to = hf;
5c28a534
 				msg->parsed_flag|=HDR_REFER_TO_F;
8b482f1a
 				break;
8a4f3a74
 			case HDR_SESSIONEXPIRES_T:
 				if (msg->session_expires==0) msg->session_expires = hf;
 				msg->parsed_flag|=HDR_SESSIONEXPIRES_F;
 				break;
 			case HDR_MIN_SE_T:
 				if (msg->min_se==0) msg->min_se = hf;
 				msg->parsed_flag|=HDR_MIN_SE_F;
 				break;
48862405
 			case HDR_SUBSCRIPTION_STATE_T:
 				if (msg->subscription_state==0) msg->subscription_state = hf;
 				msg->parsed_flag|=HDR_SUBSCRIPTION_STATE_F;
 				break;
5c28a534
 			case HDR_VIA_T:
 				msg->parsed_flag|=HDR_VIA_F;
 				DBG("parse_headers: Via found, flags=%llx\n",
 						(unsigned long long)flags);
8c7976a9
 				if (msg->via1==0) {
6984881e
 					DBG("parse_headers: this is the first via\n");
e72b5b50
 					msg->h_via1=hf;
 					msg->via1=hf->parsed;
 					if (msg->via1->next){
 						msg->via2=msg->via1->next;
5c28a534
 						msg->parsed_flag|=HDR_VIA2_F;
e72b5b50
 					}
8c7976a9
 				}else if (msg->via2==0){
e72b5b50
 					msg->h_via2=hf;
 					msg->via2=hf->parsed;
5c28a534
 					msg->parsed_flag|=HDR_VIA2_F;
6984881e
 					DBG("parse_headers: this is the second via\n");
e72b5b50
 				}
 				break;
e7317b87
 			case HDR_DATE_T:
 				if (msg->date==0) msg->date=hf;
 				msg->parsed_flag|=HDR_DATE_F;
 				break;
 			case HDR_IDENTITY_T:
 				if (msg->identity==0) msg->identity=hf;
 				msg->parsed_flag|=HDR_IDENTITY_F;
 				break;
 			case HDR_IDENTITY_INFO_T:
 				if (msg->identity_info==0) msg->identity_info=hf;
 				msg->parsed_flag|=HDR_IDENTITY_INFO_F;
 				break;
e430fa02
 		    case HDR_PATH_T:
 				if (msg->path==0) msg->path=hf;
 				msg->parsed_flag|=HDR_PATH_F;
 				break;
87d84978
 		    case HDR_PRIVACY_T:
 				if (msg->privacy==0) msg->privacy=hf;
 				msg->parsed_flag|=HDR_PRIVACY_F;
 				break;
2163a7f7
 		    case HDR_PAI_T:
 				if (msg->pai==0) msg->pai=hf;
 				msg->parsed_flag|=HDR_PAI_F;
 				break;
 		    case HDR_PPI_T:
 				if (msg->ppi==0) msg->ppi=hf;
 				msg->parsed_flag|=HDR_PPI_F;
 				break;
14babe14
 		    case HDR_REASON_T:
 				msg->parsed_flag|=HDR_REASON_F;
 				break;
e72b5b50
 			default:
 				LOG(L_CRIT, "BUG: parse_headers: unknown header type %d\n",
 							hf->type);
 				goto error;
 		}
 		/* add the header to the list*/
 		if (msg->last_header==0){
 			msg->headers=hf;
 			msg->last_header=hf;
 		}else{
 			msg->last_header->next=hf;
 			msg->last_header=hf;
 		}
68adfaee
 #ifdef EXTRA_DEBUG
049f64c2
 		DBG("header field type %d, name=<%.*s>, body=<%.*s>\n",
67386619
 			hf->type,
 			hf->name.len, ZSW(hf->name.s),
6b6f226f
 			hf->body.len, ZSW(hf->body.s));
68adfaee
 #endif
e72b5b50
 		tmp=rest;
 	}
 skip:
 	msg->unparsed=tmp;
418a2312
 	/* restore original flags */
 	msg->parsed_flag |= orig_flag;
e72b5b50
 	return 0;
f27f8905
 
e72b5b50
 error:
1400b772
 	ser_error=E_BAD_REQ;
22d4aa5d
 	if (hf) pkg_free(hf);
418a2312
 	/* restore original flags */
 	msg->parsed_flag |= orig_flag;
e72b5b50
 	return -1;
 }
 
 
512dcd98
 
888ca09d
 
 
 /* returns 0 if ok, -1 for errors */
a8e108ec
 int parse_msg(char* const buf, const unsigned int len, struct sip_msg* const msg)
888ca09d
 {
 
e22bbdb8
 	char *tmp;
888ca09d
 	char* rest;
f8d46776
 	struct msg_start *fl;
888ca09d
 	int offset;
5c28a534
 	hdr_flags_t flags;
888ca09d
 
 	/* eat crlf from the beginning */
 	for (tmp=buf; (*tmp=='\n' || *tmp=='\r')&&
 			tmp-buf < len ; tmp++);
 	offset=tmp-buf;
f8d46776
 	fl=&(msg->first_line);
 	rest=parse_first_line(tmp, len-offset, fl);
888ca09d
 	offset+=rest-tmp;
 	tmp=rest;
f8d46776
 	switch(fl->type){
888ca09d
 		case SIP_INVALID:
efeaaf53
 			DBG("parse_msg: invalid message\n");
888ca09d
 			goto error;
 			break;
 		case SIP_REQUEST:
efeaaf53
 			DBG("SIP Request:\n");
049f64c2
 			DBG(" method:  <%.*s>\n",fl->u.request.method.len,
6b6f226f
 				ZSW(fl->u.request.method.s));
049f64c2
 			DBG(" uri:     <%.*s>\n",fl->u.request.uri.len,
6b6f226f
 				ZSW(fl->u.request.uri.s));
049f64c2
 			DBG(" version: <%.*s>\n",fl->u.request.version.len,
6b6f226f
 				ZSW(fl->u.request.version.s));
5c28a534
 			flags=HDR_VIA_F;
888ca09d
 			break;
 		case SIP_REPLY:
efeaaf53
 			DBG("SIP Reply  (status):\n");
049f64c2
 			DBG(" version: <%.*s>\n",fl->u.reply.version.len,
6b6f226f
 					ZSW(fl->u.reply.version.s));
049f64c2
 			DBG(" status:  <%.*s>\n", fl->u.reply.status.len,
6b6f226f
 					ZSW(fl->u.reply.status.s));
049f64c2
 			DBG(" reason:  <%.*s>\n", fl->u.reply.reason.len,
6b6f226f
 					ZSW(fl->u.reply.reason.s));
caf80ae6
 			/* flags=HDR_VIA | HDR_VIA2; */
 			/* we don't try to parse VIA2 for local messages; -Jiri */
5c28a534
 			flags=HDR_VIA_F;
888ca09d
 			break;
 		default:
f8d46776
 			DBG("unknown type %d\n",fl->type);
e22bbdb8
 			goto error;
888ca09d
 	}
e72b5b50
 	msg->unparsed=tmp;
888ca09d
 	/*find first Via: */
590e1497
 	if (parse_headers(msg, flags, 0)==-1) goto error;
888ca09d
 
25b49bb4
 #ifdef EXTRA_DEBUG
888ca09d
 	/* dump parsed data */
e72b5b50
 	if (msg->via1){
da589b75
 		DBG("first via: <%.*s/%.*s/%.*s> <%.*s:%.*s(%d)>",
67386619
 			msg->via1->name.len,
 			ZSW(msg->via1->name.s),
049f64c2
 			msg->via1->version.len,
6b6f226f
 			ZSW(msg->via1->version.s),
3fe17de9
 			msg->via1->transport.len,
67386619
 			ZSW(msg->via1->transport.s),
049f64c2
 			msg->via1->host.len,
6b6f226f
 			ZSW(msg->via1->host.s),
67386619
 			msg->via1->port_str.len,
 			ZSW(msg->via1->port_str.s),
049f64c2
 			msg->via1->port);
67386619
 		if (msg->via1->params.s)  DBG(";<%.*s>",
6b6f226f
 				msg->via1->params.len, ZSW(msg->via1->params.s));
67386619
 		if (msg->via1->comment.s)
 				DBG(" <%.*s>",
6b6f226f
 					msg->via1->comment.len, ZSW(msg->via1->comment.s));
350c5a16
 		DBG ("\n");
 	}
e72b5b50
 	if (msg->via2){
da589b75
 		DBG("second via: <%.*s/%.*s/%.*s> <%.*s:%.*s(%d)>",
67386619
 			msg->via2->name.len,
 			ZSW(msg->via2->name.s),
049f64c2
 			msg->via2->version.len,
6b6f226f
 			ZSW(msg->via2->version.s),
67386619
 			msg->via2->transport.len,
 			ZSW(msg->via2->transport.s),
049f64c2
 			msg->via2->host.len,
6b6f226f
 			ZSW(msg->via2->host.s),
67386619
 			msg->via2->port_str.len,
 			ZSW(msg->via2->port_str.s),
049f64c2
 			msg->via2->port);
67386619
 		if (msg->via2->params.s)  DBG(";<%.*s>",
6b6f226f
 				msg->via2->params.len, ZSW(msg->via2->params.s));
67386619
 		if (msg->via2->comment.s) DBG(" <%.*s>",
6b6f226f
 				msg->via2->comment.len, ZSW(msg->via2->comment.s));
22d4aa5d
 		DBG ("\n");
888ca09d
 	}
 #endif
67386619
 
888ca09d
 
25b49bb4
 #ifdef EXTRA_DEBUG
efeaaf53
 	DBG("exiting parse_msg\n");
888ca09d
 #endif
 
 	return 0;
67386619
 
888ca09d
 error:
96b76347
 	/* more debugging, msg->orig is/should be null terminated*/
b198224d
 	LOG(cfg_get(core, core_cfg, corelog), "ERROR: parse_msg: message=<%.*s>\n",
6b6f226f
 			(int)msg->len, ZSW(msg->buf));
888ca09d
 	return -1;
 }
 
5ada8f8a
 
 
0498ceb9
 void free_reply_lump( struct lump_rpl *lump)
 {
 	struct lump_rpl *foo, *bar;
 	for(foo=lump;foo;)
 	{
 		bar=foo->next;
 		free_lump_rpl(foo);
 		foo = bar;
 	}
 }
e72b5b50
 
22d4aa5d
 
 /*only the content*/
a8e108ec
 void free_sip_msg(struct sip_msg* const msg)
22d4aa5d
 {
cae96597
 	reset_new_uri(msg);
 	reset_dst_uri(msg);
 	reset_path_vector(msg);
 	reset_instance(msg);
 	reset_ruid(msg);
 	reset_ua(msg);
6bd84753
 	if (msg->headers)     free_hdr_field_lst(msg->headers);
5a897710
 	if (msg->body && msg->body->free) msg->body->free(&msg->body);
22d4aa5d
 	if (msg->add_rm)      free_lump_list(msg->add_rm);
4c37101e
 	if (msg->body_lumps)  free_lump_list(msg->body_lumps);
0498ceb9
 	if (msg->reply_lump)   free_reply_lump(msg->reply_lump);
949e1f3c
 	msg_ldata_reset(msg);
dda9dab1
 	/* don't free anymore -- now a pointer to a static buffer */
 #	ifdef DYN_BUF
67386619
 	pkg_free(msg->buf);
dda9dab1
 #	endif
22d4aa5d
 }
 
cae96597
 /**
  * reset new uri value
  */
 void reset_new_uri(struct sip_msg* const msg)
 {
 	if(msg->new_uri.s != 0) {
 		pkg_free(msg->new_uri.s);
 	}
 	msg->new_uri.s = 0;
 	msg->new_uri.len = 0;
 	msg->parsed_uri_ok = 0;
 }
 
22d4aa5d
 
846a7aa0
 /*
  * Make a private copy of the string and assign it to dst_uri
  */
a8e108ec
 int set_dst_uri(struct sip_msg* const msg, const str* const uri)
846a7aa0
 {
 	char* ptr;
 
feb3478b
 	if (unlikely(!msg || !uri)) {
846a7aa0
 		LOG(L_ERR, "set_dst_uri: Invalid parameter value\n");
 		return -1;
 	}
 
feb3478b
 	if (unlikely(uri->len == 0)) {
 		reset_dst_uri(msg);
 	}else if (msg->dst_uri.s && (msg->dst_uri.len >= uri->len)) {
846a7aa0
 		memcpy(msg->dst_uri.s, uri->s, uri->len);
 		msg->dst_uri.len = uri->len;
 	} else {
 		ptr = (char*)pkg_malloc(uri->len);
 		if (!ptr) {
 			LOG(L_ERR, "set_dst_uri: Not enough memory\n");
 			return -1;
 		}
 
 		memcpy(ptr, uri->s, uri->len);
 		if (msg->dst_uri.s) pkg_free(msg->dst_uri.s);
 		msg->dst_uri.s = ptr;
 		msg->dst_uri.len = uri->len;
 	}
 	return 0;
 }
07689d3a
 
 
a8e108ec
 void reset_dst_uri(struct sip_msg* const msg)
07689d3a
 {
 	if(msg->dst_uri.s != 0) {
 		pkg_free(msg->dst_uri.s);
 	}
 	msg->dst_uri.s = 0;
 	msg->dst_uri.len = 0;
 }
7b878801
 
d752afff
 int set_path_vector(struct sip_msg* msg, str* path)
 {
 	char* ptr;
 
feb3478b
 	if (unlikely(!msg || !path)) {
d752afff
 		LM_ERR("invalid parameter value\n");
 		return -1;
 	}
 
feb3478b
 	if (unlikely(path->len == 0)) {
 		reset_path_vector(msg);
 	} else if (msg->path_vec.s && (msg->path_vec.len >= path->len)) {
d752afff
 		memcpy(msg->path_vec.s, path->s, path->len);
 		msg->path_vec.len = path->len;
 	} else {
 		ptr = (char*)pkg_malloc(path->len);
 		if (!ptr) {
 			LM_ERR("not enough pkg memory\n");
 			return -1;
 		}
 
 		memcpy(ptr, path->s, path->len);
 		if (msg->path_vec.s) pkg_free(msg->path_vec.s);
 		msg->path_vec.s = ptr;
 		msg->path_vec.len = path->len;
 	}
 	return 0;
 }
7b878801
 
9c2f5f65
 
6742b34b
 void reset_path_vector(struct sip_msg* const msg)
9c2f5f65
 {
4ab0f53f
 	/* only free path vector from pkg IFF it is still in pkg... - ie. if msg is shm we don't free... */
1ccdadc8
 	if (!(msg->msg_flags&FL_SHM_CLONE)) {
9e756aea
 		if (msg->path_vec.s)
 			pkg_free(msg->path_vec.s);
1ccdadc8
 		msg->path_vec.s = 0;
 		msg->path_vec.len = 0;
9c2f5f65
 	}
 }
 
 
55e78206
 int set_instance(struct sip_msg* msg, str* instance)
 {
 	char* ptr;
 
 	if (unlikely(!msg || !instance)) {
 		LM_ERR("invalid instance parameter value\n");
 		return -1;
 	}
 
 	if (unlikely(instance->len == 0)) {
 		reset_instance(msg);
 	} else if (msg->instance.s && (msg->instance.len >= instance->len)) {
 		memcpy(msg->instance.s, instance->s, instance->len);
 		msg->instance.len = instance->len;
 	} else {
 		ptr = (char*)pkg_malloc(instance->len);
 		if (!ptr) {
 			LM_ERR("not enough pkg memory for instance\n");
 			return -1;
 		}
 		memcpy(ptr, instance->s, instance->len);
 		if (msg->instance.s) pkg_free(msg->instance.s);
 		msg->instance.s = ptr;
 		msg->instance.len = instance->len;
 	}
 	return 0;
 }
 
 
 void reset_instance(struct sip_msg* const msg)
 {
 	if(msg->instance.s != 0) {
 		pkg_free(msg->instance.s);
 	}
 	msg->instance.s = 0;
 	msg->instance.len = 0;
 }
 
 
e3ba8f38
 int set_ruid(struct sip_msg* msg, str* ruid)
 {
 	char* ptr;
 
 	if (unlikely(!msg || !ruid)) {
 		LM_ERR("invalid ruid parameter value\n");
 		return -1;
 	}
 
 	if (unlikely(ruid->len == 0)) {
 		reset_ruid(msg);
 	} else if (msg->ruid.s && (msg->ruid.len >= ruid->len)) {
 		memcpy(msg->ruid.s, ruid->s, ruid->len);
 		msg->ruid.len = ruid->len;
 	} else {
 		ptr = (char*)pkg_malloc(ruid->len);
 		if (!ptr) {
 			LM_ERR("not enough pkg memory for ruid\n");
 			return -1;
 		}
 		memcpy(ptr, ruid->s, ruid->len);
 		if (msg->ruid.s) pkg_free(msg->ruid.s);
 		msg->ruid.s = ptr;
 		msg->ruid.len = ruid->len;
 	}
 	return 0;
 }
 
 
 void reset_ruid(struct sip_msg* const msg)
 {
 	if(msg->ruid.s != 0) {
 		pkg_free(msg->ruid.s);
 	}
 	msg->ruid.s = 0;
 	msg->ruid.len = 0;
 }
 
 
8ca114df
 int set_ua(struct sip_msg* msg, str* location_ua)
 {
 	char* ptr;
 
 	if (unlikely(!msg || !location_ua)) {
 		LM_ERR("invalid location_ua parameter value\n");
 		return -1;
 	}
 
 	if (unlikely(location_ua->len == 0)) {
 		reset_ua(msg);
 	} else if (msg->location_ua.s && (msg->location_ua.len >= location_ua->len)) {
 		memcpy(msg->location_ua.s, location_ua->s, location_ua->len);
 		msg->location_ua.len = location_ua->len;
 	} else {
 		ptr = (char*)pkg_malloc(location_ua->len);
 		if (!ptr) {
 			LM_ERR("not enough pkg memory for location_ua\n");
 			return -1;
 		}
 		memcpy(ptr, location_ua->s, location_ua->len);
 		if (msg->location_ua.s) pkg_free(msg->location_ua.s);
 		msg->location_ua.s = ptr;
 		msg->location_ua.len = location_ua->len;
 	}
 	return 0;
 }
 
 
 void reset_ua(struct sip_msg* const msg)
 {
 	if(msg->location_ua.s != 0) {
 		pkg_free(msg->location_ua.s);
 	}
 	msg->location_ua.s = 0;
 	msg->location_ua.len = 0;
 }
 
949e1f3c
 /**
  * reset content of msg->ldv (msg_ldata_t structure)
  */
 void msg_ldata_reset(sip_msg_t *msg)
 {
 	if(msg==NULL)
 		return;
 	memset(&msg->ldv, 0, sizeof(msg_ldata_t));
 }
 
8ca114df
 
6742b34b
 hdr_field_t* get_hdr(const sip_msg_t* const msg, const enum _hdr_types_t ht)
7b878801
 {
a4485985
 	hdr_field_t *hdr;
7b878801
 
e0404857
 	if (msg->parsed_flag & HDR_T2F(ht))
 		for(hdr = msg->headers; hdr; hdr = hdr->next) {
 			if(hdr->type == ht) return hdr;
 		}
7b878801
 	return NULL;
 }
 
 
6742b34b
 hdr_field_t* next_sibling_hdr(const hdr_field_t* const hf)
a4485985
 {
 	hdr_field_t *hdr;
 
7b878801
 	for(hdr = hf->next; hdr; hdr = hdr->next) {
 		if(hdr->type == hf->type) return hdr;
 	}
 	return NULL;
 }
a4485985
 
6742b34b
 hdr_field_t* get_hdr_by_name(const sip_msg_t* const msg, const char* const name, const int name_len)
a4485985
 {
 	hdr_field_t *hdr;
 
 	for(hdr = msg->headers; hdr; hdr = hdr->next) {
 		if(hdr->name.len == name_len && *hdr->name.s==*name
 				&& strncmp(hdr->name.s, name, name_len)==0)
 			return hdr;
 	}
 	return NULL;
 }
 
6742b34b
 /** not used yet */
 hdr_field_t* next_sibling_hdr_by_name(const hdr_field_t* const hf)
a4485985
 {
 	hdr_field_t *hdr;
 
 	for(hdr = hf->next; hdr; hdr = hdr->next) {
 		if(hdr->name.len == hf->name.len && *hdr->name.s==*hf->name.s
 				&& strncmp(hdr->name.s, hf->name.s, hf->name.len)==0)
 			return hdr;
 	}
 	return NULL;
 }
cf9269d7
 
 /**
  * set msg context id
  * - return: -1 on error; 0 - on set
  */
a8e108ec
 int msg_ctx_id_set(const sip_msg_t* const msg, msg_ctx_id_t* const mid)
cf9269d7
 {
 	if(msg==NULL || mid==NULL)
 		return -1;
 	mid->msgid = msg->id;
 	mid->pid = msg->pid;
 	return 0;
 }
 
 /**
  * check msg context id
  * - return: -1 on error; 0 - on no match; 1 - on match
  */
a8e108ec
 int msg_ctx_id_match(const sip_msg_t* const msg, const msg_ctx_id_t* const mid)
cf9269d7
 {
 	if(msg==NULL || mid==NULL)
 		return -1;
 	if(msg->id != mid->msgid || msg->pid!=mid->pid)
 		return 0;
 	return 1;
 }
d4ed4771
 
 /**
  * set msg time value
  */
a8e108ec
 int msg_set_time(sip_msg_t* const msg)
d4ed4771
 {
 	if(unlikely(msg==NULL))
 		return -2;
 	if(msg->tval.tv_sec!=0)
 		return 0;
 	return gettimeofday(&msg->tval, NULL);
 }
b81dff6a
 
 /**
  * get source ip, port and protocol in SIP URI format
  * - tmode - 0: short format (transport=udp is not added, being default)
  */
 int get_src_uri(sip_msg_t *m, int tmode, str *uri)
 {
 	static char buf[MAX_URI_SIZE];
 	char* p;
 	str ip, port;
 	int len;
 	str proto;
 
 	if (!uri || !m) {
 		LM_ERR("invalid parameter value\n");
 		return -1;
 	}
 
 	if(tmode==0) {
 		switch(m->rcv.proto) {
 			case PROTO_NONE:
 			case PROTO_UDP:
 				proto.s = 0; /* Do not add transport parameter, UDP is default */
 				proto.len = 0;
 			break;
 			default:
 				if(get_valid_proto_string(m->rcv.proto, 1, 0, &proto)<0) {
 					LM_ERR("unknown transport protocol\n");
 					return -1;
 				}
 		}
 	} else {
 		if(get_valid_proto_string(m->rcv.proto, 1, 0, &proto)<0) {
 			LM_ERR("unknown transport protocol\n");
 			return -1;
 		}
 	}
 
 	ip.s = ip_addr2a(&m->rcv.src_ip);
 	ip.len = strlen(ip.s);
 
 	port.s = int2str(m->rcv.src_port, &port.len);
 
 	len = 4 + ip.len + 2*(m->rcv.src_ip.af==AF_INET6)+ 1 + port.len;
 	if (proto.s) {
 		len += TRANSPORT_PARAM_LEN;
 		len += proto.len;
 	}
 
 	if (len > MAX_URI_SIZE) {
 		LM_ERR("buffer too small\n");
 		return -1;
 	}
 
 	p = buf;
 	memcpy(p, "sip:", 4);
 	p += 4;
 
 	if (m->rcv.src_ip.af==AF_INET6)
 		*p++ = '[';
 	memcpy(p, ip.s, ip.len);
 	p += ip.len;
 	if (m->rcv.src_ip.af==AF_INET6)
 		*p++ = ']';
 
 	*p++ = ':';
 
 	memcpy(p, port.s, port.len);
 	p += port.len;
 
 	if (proto.s) {
 		memcpy(p, TRANSPORT_PARAM, TRANSPORT_PARAM_LEN);
 		p += TRANSPORT_PARAM_LEN;
 
 		memcpy(p, proto.s, proto.len);
 		p += proto.len;
 	}
 
 	uri->s = buf;
 	uri->len = len;
 
 	return 0;
 }