parser/msg_parser.c
512dcd98
 /*
  * $Id$
  *
67386619
  * sip msg. header proxy parser
512dcd98
  *
7dd0b342
  *
c32feee5
  * Copyright (C) 2001-2003 FhG Fokus
7dd0b342
  *
  * This file is part of ser, a free SIP server.
  *
  * ser is free software; you can redistribute it and/or modify
  * 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
  *
  * For a license to use the ser software under conditions
  * other than those described here, or to purchase support for this
  * software, please contact iptel.org by e-mail at the following addresses:
  *    info@iptel.org
  *
  * ser is distributed in the hope that it will be useful,
  * 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
7dd0b342
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
1540fad1
  *
  * History:
  * ---------
f15bede1
  *  2003-02-28  scratchpad compatibility abandoned (jiri)
  *  2003-01-29  scrathcpad removed (jiri)
  *  2003-01-27  next baby-step to removing ZT - PRESERVE_ZT (jiri)
  *  2003-03-31  removed msg->repl_add_rm (andrei)
6b6f226f
  *  2003-04-26 ZSW (jiri)
71be0c4a
  *  2003-05-01  parser extended to support Accept header field (janakj)
5c28a534
  *  2005-02-23  parse_headers uses hdr_flags_t now (andrei)
7418afcf
  *  2005-03-02  free_via_list(vb) on via parse error (andrei)
52553188
  *  2007-01-26  parser extended to support Identity, Identity-info and Date
e7317b87
  *		header fields (gergo)
512dcd98
  */
 
7dd0b342
 
888ca09d
 #include <string.h>
3e429f5c
 #include <stdlib.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"
 #include "../globals.h"
2bb60634
 #include "parse_hname2.h"
855c2e68
 #include "parse_uri.h"
ec147e2e
 #include "parse_content.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;
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)*/
e72b5b50
 char* get_hdr_field(char* buf, char* end, struct hdr_field* hdr)
f8d46776
 {
e72b5b50
 
f8d46776
 	char* tmp;
 	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
 
 	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");
22d4aa5d
 				pkg_free(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");
 				pkg_free(to_b);
 				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_ACCEPTDISPOSITION_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:
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");
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
 */
5c28a534
 int parse_headers(struct sip_msg* msg, hdr_flags_t flags, 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
 
8dd85148
 	if (next) {
 		orig_flag = msg->parsed_flag;
 		msg->parsed_flag &= ~flags;
219627a2
 	}else
67386619
 		orig_flag=0;
 
5c28a534
 	DBG("parse_headers: flags=%llx\n", (unsigned long long)flags);
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:
e72b5b50
 				LOG(L_INFO,"ERROR: bad header  field\n");
 				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:
5c28a534
 			case HDR_OTHER_T: /*do nothing*/
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_ACCEPTDISPOSITION_T:
6a2b0dec
 				if (msg->accept_disposition==0) msg->accept_disposition = hf;
5c28a534
 				msg->parsed_flag|=HDR_ACCEPTDISPOSITION_F;
2f43c732
 				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;
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;
 	return 0;
f27f8905
 
e72b5b50
 error:
1400b772
 	ser_error=E_BAD_REQ;
22d4aa5d
 	if (hf) pkg_free(hf);
590e1497
 	if (next) msg->parsed_flag |= orig_flag;
e72b5b50
 	return -1;
 }
 
 
512dcd98
 
888ca09d
 
 
 /* returns 0 if ok, -1 for errors */
 int parse_msg(char* buf, unsigned int len, struct sip_msg* msg)
 {
 
e22bbdb8
 	char *tmp;
888ca09d
 	char* rest;
 	char* first_via;
 	char* second_via;
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);
b6f4c1df
 #if 0
 	rest=parse_fline(tmp, buf+len, fl);
 #endif
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: */
 	first_via=0;
 	second_via=0;
590e1497
 	if (parse_headers(msg, flags, 0)==-1) goto error;
888ca09d
 
25b49bb4
 #ifdef EXTRA_DEBUG
888ca09d
 	/* dump parsed data */
e72b5b50
 	if (msg->via1){
049f64c2
 		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){
049f64c2
 		DBG(" first  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*/
67386619
 	LOG(L_ERR, "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*/
 void free_sip_msg(struct sip_msg* msg)
 {
 	if (msg->new_uri.s) { pkg_free(msg->new_uri.s); msg->new_uri.len=0; }
846a7aa0
 	if (msg->dst_uri.s) { pkg_free(msg->dst_uri.s); msg->dst_uri.len=0; }
6bd84753
 	if (msg->headers)     free_hdr_field_lst(msg->headers);
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);
dda9dab1
 	/* don't free anymore -- now a pointer to a static buffer */
 #	ifdef DYN_BUF
67386619
 	pkg_free(msg->buf);
dda9dab1
 #	endif
22d4aa5d
 }
 
 
846a7aa0
 /*
  * Make a private copy of the string and assign it to dst_uri
  */
 int set_dst_uri(struct sip_msg* msg, str* uri)
 {
 	char* ptr;
 
 	if (!msg || !uri) {
 		LOG(L_ERR, "set_dst_uri: Invalid parameter value\n");
 		return -1;
 	}
 
 	if (msg->dst_uri.s && (msg->dst_uri.len >= uri->len)) {
 		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;
 }