xref: /onnv-gate/usr/src/lib/libsip/common/sip_parse_hdrs.c (revision 5092:0cbd682a52d4)
12882Svi117747 /*
22882Svi117747  * CDDL HEADER START
32882Svi117747  *
42882Svi117747  * The contents of this file are subject to the terms of the
52882Svi117747  * Common Development and Distribution License (the "License").
62882Svi117747  * You may not use this file except in compliance with the License.
72882Svi117747  *
82882Svi117747  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
92882Svi117747  * or http://www.opensolaris.org/os/licensing.
102882Svi117747  * See the License for the specific language governing permissions
112882Svi117747  * and limitations under the License.
122882Svi117747  *
132882Svi117747  * When distributing Covered Code, include this CDDL HEADER in each
142882Svi117747  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
152882Svi117747  * If applicable, add the following below this CDDL HEADER, with the
162882Svi117747  * fields enclosed by brackets "[]" replaced with your own identifying
172882Svi117747  * information: Portions Copyright [yyyy] [name of copyright owner]
182882Svi117747  *
192882Svi117747  * CDDL HEADER END
202882Svi117747  */
212882Svi117747 
222882Svi117747 /*
233439Svi117747  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
242882Svi117747  * Use is subject to license terms.
252882Svi117747  */
262882Svi117747 
272882Svi117747 #pragma ident	"%Z%%M%	%I%	%E% SMI"
282882Svi117747 
293439Svi117747 #include <ctype.h>
303439Svi117747 #include <errno.h>
313439Svi117747 #include <stdlib.h>
323439Svi117747 #include <strings.h>
333439Svi117747 #include <sip.h>
343439Svi117747 
352882Svi117747 #include "sip_msg.h"
362882Svi117747 #include "sip_miscdefs.h"
372882Svi117747 #include "sip_parse_generic.h"
383439Svi117747 #include "sip_parse_uri.h"
393439Svi117747 
402882Svi117747 
412882Svi117747 /*
422882Svi117747  * Accept = "Accept" HCOLON [ accept-range *(COMMA accept-range) ]
432882Svi117747  * accept-range = media-range *(SEMI accept-param)
442882Svi117747  * media-range = ("* / *" |  (m-type SLASH "*") | (m-type SLASH m-subtype))
452882Svi117747  *		*(SEMI m-param)
462882Svi117747  * accept-param = ("q" EQUAL qvalue) | generic-param
472882Svi117747  * qvalue = ("0" ["." 0*3DIGIT]) | ("1" ["." 0*3DIGIT])
482882Svi117747  * generic-param = token [ EQUAL gen-value]
492882Svi117747  * gen-value = token | host | quoted-str
502882Svi117747  */
512882Svi117747 int
sip_parse_acpt_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)522882Svi117747 sip_parse_acpt_header(_sip_header_t *sip_header, sip_parsed_header_t **header)
532882Svi117747 {
542882Svi117747 	if (sip_is_empty_hdr(sip_header))
552882Svi117747 		return (sip_parse_hdr_empty(sip_header, header));
562882Svi117747 	return (sip_parse_hdr_parser1(sip_header, header, SIP_SLASH));
572882Svi117747 }
582882Svi117747 
592882Svi117747 /*
602882Svi117747  * Accept-Encoding = "Accept-Encoding" ":" 1#(codings [ ";" "q" "=" qval])
612882Svi117747  * codings = (content-coding | "*")
622882Svi117747  * content-coding = token
632882Svi117747  */
642882Svi117747 int
sip_parse_acpt_encode_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)652882Svi117747 sip_parse_acpt_encode_header(_sip_header_t *sip_header,
662882Svi117747 	sip_parsed_header_t **header)
672882Svi117747 {
682882Svi117747 	return (sip_parse_hdr_parser1(sip_header, header, (char)NULL));
692882Svi117747 }
702882Svi117747 
712882Svi117747 /*
722882Svi117747  * Accept-Language = "Accept-Language" ":" [ lang * (COMMA lang) ]
732882Svi117747  * lang = lang-range *(SEMI accept-param)
742882Svi117747  * lang-range = ((1*8ALPHA * ("-" 1*8ALPHA)) | "*"
752882Svi117747  */
762882Svi117747 int
sip_parse_acpt_lang_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)772882Svi117747 sip_parse_acpt_lang_header(_sip_header_t *sip_header,
782882Svi117747 	sip_parsed_header_t **header)
792882Svi117747 {
802882Svi117747 	if (sip_is_empty_hdr(sip_header))
812882Svi117747 		return (sip_parse_hdr_empty(sip_header, header));
822882Svi117747 	return (sip_parse_hdr_parser1(sip_header, header, (char)NULL));
832882Svi117747 }
842882Svi117747 
852882Svi117747 /*
862882Svi117747  * Alert-Info = "Alert-Info" ":" alert-param *(COMMA alert-param)
872882Svi117747  * alert-param = LAQUOT absoluteURI RAQUOT * (SEMI generic-param)
882882Svi117747  */
892882Svi117747 int
sip_parse_alert_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)902882Svi117747 sip_parse_alert_header(_sip_header_t *sip_header, sip_parsed_header_t **header)
912882Svi117747 {
922882Svi117747 	return (sip_parse_hdr_parser3(sip_header, header, SIP_STR_VAL, B_TRUE));
932882Svi117747 }
942882Svi117747 
952882Svi117747 /*
962882Svi117747  * Allow = "Allow" ":" method-name1[, method-name2..]
972882Svi117747  */
982882Svi117747 int
sip_parse_allow_header(_sip_header_t * hdr,sip_parsed_header_t ** phdr)992882Svi117747 sip_parse_allow_header(_sip_header_t *hdr, sip_parsed_header_t **phdr)
1002882Svi117747 {
1012882Svi117747 	sip_parsed_header_t	*parsed_header;
1022882Svi117747 	sip_hdr_value_t		*value = NULL;
1032882Svi117747 	sip_hdr_value_t		*last_value = NULL;
1042882Svi117747 	int			len;
1052882Svi117747 	int			i;
1062882Svi117747 	int			ret;
1072882Svi117747 	boolean_t		multi_value = B_FALSE;
1082882Svi117747 
1092882Svi117747 	if ((ret = sip_prim_parsers(hdr, phdr)) != 0)
1102882Svi117747 		return (ret);
1112882Svi117747 
1122882Svi117747 	if (*phdr != NULL)
1132882Svi117747 		return (0);
1142882Svi117747 
1152882Svi117747 	parsed_header = calloc(1, sizeof (sip_parsed_header_t));
1162882Svi117747 	if (parsed_header == NULL)
1172882Svi117747 		return (ENOMEM);
1182882Svi117747 	parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1;
1192882Svi117747 	parsed_header->sip_header = hdr;
1202882Svi117747 
1212882Svi117747 	while (hdr->sip_hdr_current < hdr->sip_hdr_end) {
1222882Svi117747 		value = calloc(1, sizeof (sip_hdr_value_t));
1232882Svi117747 		if (value == NULL) {
1242882Svi117747 			sip_free_phdr(parsed_header);
1252882Svi117747 			return (ENOMEM);
1262882Svi117747 		}
1272882Svi117747 		if (last_value != NULL)
1282882Svi117747 			last_value->sip_next_value = value;
1292882Svi117747 		else
1302882Svi117747 			parsed_header->value = (sip_value_t *)value;
1312882Svi117747 
1322882Svi117747 		value->sip_value_start = hdr->sip_hdr_current;
1332882Svi117747 		value->sip_value_header = parsed_header;
1342882Svi117747 
1352882Svi117747 		if (sip_find_separator(hdr, SIP_COMMA, (char)NULL,
136*5092Sgm209912 		    (char)NULL, B_FALSE) == 0) {
1372882Svi117747 			multi_value = B_TRUE;
1382882Svi117747 		}
1392882Svi117747 
1402882Svi117747 		len = hdr->sip_hdr_current - value->sip_value_start;
1412882Svi117747 		for (i = 1; i < MAX_SIP_METHODS; i++) {
1422882Svi117747 			if (strncmp(sip_methods[i].name, value->sip_value_start,
1432882Svi117747 			    len) == 0) {
1442882Svi117747 				break;
1452882Svi117747 			}
1462882Svi117747 		}
1472882Svi117747 		if (i >= MAX_SIP_METHODS) {
1482882Svi117747 			value->int_val = 0;
1492882Svi117747 			value->sip_value_state = SIP_VALUE_BAD;
1502882Svi117747 			if (multi_value)
1512882Svi117747 				goto next_val;
1522882Svi117747 			else
1532882Svi117747 				goto end;
1542882Svi117747 		}
1552882Svi117747 		value->int_val = i;
1562882Svi117747 		if (!multi_value)
1572882Svi117747 			goto end;
1582882Svi117747 	next_val:
1592882Svi117747 		if (sip_find_token(hdr, SIP_COMMA) != 0)
1602882Svi117747 			break;
1612882Svi117747 		value->sip_value_end = hdr->sip_hdr_current - 1;
1622882Svi117747 		last_value = value;
1632882Svi117747 		(void) sip_skip_white_space(hdr);
1642882Svi117747 	}
1652882Svi117747 
1662882Svi117747 end:
1672882Svi117747 	*phdr = parsed_header;
1682882Svi117747 	return (0);
1692882Svi117747 }
1702882Svi117747 
1712882Svi117747 
1722882Svi117747 /*
1732882Svi117747  * Call-Info = "Call-Info" HCOLON info * (COMMA info)
1742882Svi117747  * info = LAQUOT absoluteURI RAQUOT * (SEMI info-param)
1752882Svi117747  * info-param = ("purpose" EQUAL ("icon" | "info" | "card" | token)) |
1762882Svi117747  *		 generic-param
1772882Svi117747  */
1782882Svi117747 int
sip_parse_callinfo_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)1792882Svi117747 sip_parse_callinfo_header(_sip_header_t *sip_header,
1802882Svi117747     sip_parsed_header_t **header)
1812882Svi117747 {
1822882Svi117747 	return (sip_parse_hdr_parser3(sip_header, header, SIP_STR_VAL, B_TRUE));
1832882Svi117747 }
1842882Svi117747 
1852882Svi117747 /*
1862882Svi117747  * Content-Disposition = "Content-Disposition" HCOLON disp-type *
1872882Svi117747  *			(SEMI disp-param)
1882882Svi117747  * disp-type = "render" | "session" | "icon" | "alert" | disp-ext-token
1892882Svi117747  * disp-param = handling-param | generic-param
1902882Svi117747  * handling-param = "handling" EQUAL("optional" | "required" | other-handling)
1912882Svi117747  * other-handling = token
1922882Svi117747  * disp-ext-token = token
1932882Svi117747  *
1942882Svi117747  */
1952882Svi117747 int
sip_parse_contentdis_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)1962882Svi117747 sip_parse_contentdis_header(_sip_header_t *sip_header,
1972882Svi117747     sip_parsed_header_t **header)
1982882Svi117747 {
1992882Svi117747 	return (sip_parse_hdr_parser1(sip_header, header, (char)NULL));
2002882Svi117747 }
2012882Svi117747 
2022882Svi117747 /*
2032882Svi117747  * Content-Encoding = ("Content-Encoding" | "e") HCOLON content-coding *
2042882Svi117747  *			(COMMA content-coding)
2052882Svi117747  */
2062882Svi117747 int
sip_parse_contentencode_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)2072882Svi117747 sip_parse_contentencode_header(_sip_header_t *sip_header,
2082882Svi117747     sip_parsed_header_t **header)
2092882Svi117747 {
2102882Svi117747 	return (sip_parse_hdr_parser1(sip_header, header, (char)NULL));
2112882Svi117747 }
2122882Svi117747 
2132882Svi117747 /*
2142882Svi117747  * Content-Language = ("Content-Language" | "l") HCOLON lang-tag *
2152882Svi117747  *		 (COMMA lang-tag)
2162882Svi117747  * lang-tag = primary-tag *("-" subtag)
2172882Svi117747  * prmary-tag = 1*8ALPHA
2182882Svi117747  * subtag = 1*8ALPHA
2192882Svi117747  */
2202882Svi117747 int
sip_parse_contentlang_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)2212882Svi117747 sip_parse_contentlang_header(_sip_header_t *sip_header,
2222882Svi117747     sip_parsed_header_t **header)
2232882Svi117747 {
2242882Svi117747 	return (sip_parse_hdr_parser1(sip_header, header, (char)NULL));
2252882Svi117747 }
2262882Svi117747 
2272882Svi117747 /*
2282882Svi117747  * Date = "Date" HCOLON SIPdate
2292882Svi117747  * SIPdate = wkday "," SP date1 SP time SP "GMT"
2302882Svi117747  * date1 = 2DIGIT SP mnth SP 4DIGIT; day month year
2312882Svi117747  * time = 2DIGIT ":" 2DIGIT ":" 2DIGIT
2322882Svi117747  * wkday = "Mon" | "Tue" | "Wed" | "Thu" | "Fri" | "Sat" | "Sun"
2332882Svi117747  * month = "Jan" | "Feb" etc
2342882Svi117747  */
2352882Svi117747 int
sip_parse_date_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)2362882Svi117747 sip_parse_date_header(_sip_header_t *sip_header, sip_parsed_header_t **header)
2372882Svi117747 {
2382882Svi117747 	sip_parsed_header_t	*parsed_header;
2392882Svi117747 	int			 r;
2402882Svi117747 	sip_hdr_value_t		*value = NULL;
2412882Svi117747 
2422882Svi117747 	if ((r = sip_prim_parsers(sip_header, header)) != 0)
2432882Svi117747 		return (r);
2442882Svi117747 
2452882Svi117747 	if (*header != NULL)
2462882Svi117747 		return (0);
2472882Svi117747 
2482882Svi117747 	parsed_header = calloc(1, sizeof (sip_parsed_header_t));
2492882Svi117747 	if (parsed_header == NULL)
2502882Svi117747 		return (ENOMEM);
2512882Svi117747 	parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1;
2522882Svi117747 	parsed_header->sip_header = sip_header;
2532882Svi117747 
2542882Svi117747 	value = calloc(1, sizeof (sip_hdr_value_t));
2552882Svi117747 	if (value == NULL) {
2562882Svi117747 		sip_free_phdr(parsed_header);
2572882Svi117747 		return (ENOMEM);
2582882Svi117747 	}
2592882Svi117747 	parsed_header->value = (sip_value_t *)value;
2602882Svi117747 
2612882Svi117747 	value->sip_value_start = sip_header->sip_hdr_current;
2622882Svi117747 	value->sip_value_header = parsed_header;
2632882Svi117747 	value->date_wd_ptr = sip_header->sip_hdr_current;
2642882Svi117747 	if (sip_find_token(sip_header, SIP_COMMA) == 0) {
2652882Svi117747 		value->date_wd_len = sip_header->sip_hdr_current -
2662882Svi117747 		    value->date_wd_ptr - 1;
2672882Svi117747 		sip_header->sip_hdr_current++;
2682882Svi117747 		if (sip_skip_white_space(sip_header) != 0) {
2692882Svi117747 			value->sip_value_state = SIP_VALUE_BAD;
2702882Svi117747 			return (EPROTO);
2712882Svi117747 		}
2722882Svi117747 	} else {
2732882Svi117747 		value->sip_value_state = SIP_VALUE_BAD;
2742882Svi117747 		return (EPROTO);
2752882Svi117747 	}
2762882Svi117747 
2772882Svi117747 	if (sip_skip_white_space(sip_header) != 0) {
2782882Svi117747 		value->sip_value_state = SIP_VALUE_BAD;
2792882Svi117747 		return (EPROTO);
2802882Svi117747 	}
2812882Svi117747 	r = sip_atoi(sip_header, &value->date_d);
2822882Svi117747 	if (r != 0 || value->date_d < 0 || value->date_d > 31) {
2832882Svi117747 		value->sip_value_state = SIP_VALUE_BAD;
2842882Svi117747 		return (EPROTO);
2852882Svi117747 	}
2862882Svi117747 	if (sip_skip_white_space(sip_header) != 0) {
2872882Svi117747 		value->sip_value_state = SIP_VALUE_BAD;
2882882Svi117747 		return (EPROTO);
2892882Svi117747 	}
2902882Svi117747 	value->date_m_ptr = sip_header->sip_hdr_current;
2912882Svi117747 	if (sip_find_token(sip_header, SIP_SP) == 0) {
2922882Svi117747 		value->date_m_len = sip_header->sip_hdr_current -
2932882Svi117747 		    value->date_m_ptr - 1;
2942882Svi117747 	} else {
2952882Svi117747 		value->sip_value_state = SIP_VALUE_BAD;
2962882Svi117747 		return (EPROTO);
2972882Svi117747 	}
2982882Svi117747 
2992882Svi117747 	r = sip_atoi(sip_header, &value->date_y);
3002882Svi117747 	if (r != 0 || value->date_y < 0) {
3012882Svi117747 		value->sip_value_state = SIP_VALUE_BAD;
3022882Svi117747 		return (EPROTO);
3032882Svi117747 	}
3042882Svi117747 	if (sip_skip_white_space(sip_header) != 0) {
3052882Svi117747 		value->sip_value_state = SIP_VALUE_BAD;
3062882Svi117747 		return (EPROTO);
3072882Svi117747 	}
3082882Svi117747 	value->date_t_ptr = sip_header->sip_hdr_current;
3092882Svi117747 	if (sip_find_token(sip_header, SIP_SP) == 0) {
3102882Svi117747 		value->date_t_len = sip_header->sip_hdr_current -
3112882Svi117747 		    value->date_t_ptr - 1;
3122882Svi117747 	} else {
3132882Svi117747 		value->sip_value_state = SIP_VALUE_BAD;
3142882Svi117747 		return (EPROTO);
3152882Svi117747 	}
3162882Svi117747 
3172882Svi117747 	value->date_tz_ptr =  sip_header->sip_hdr_current;
3182882Svi117747 	/*
3192882Svi117747 	 * minus 2 to get rid of the CRLF
3202882Svi117747 	 */
3212882Svi117747 	value->date_tz_len = sip_header->sip_hdr_end -
3222882Svi117747 	    sip_header->sip_hdr_current - 2;
3232882Svi117747 
3242882Svi117747 	*header = parsed_header;
3252882Svi117747 
3262882Svi117747 	sip_header->sip_hdr_parsed = *header;
3272882Svi117747 	return (0);
3282882Svi117747 }
3292882Svi117747 
3302882Svi117747 /*
3312882Svi117747  * Error-Info = "Error-Info" HCOLON error-uri *(COMMA error-uri)
3322882Svi117747  * error-uri = LAQUOT absoluteURI RAQUOT *(SEMI generic-param)
3332882Svi117747  */
3342882Svi117747 int
sip_parse_errorinfo_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)3352882Svi117747 sip_parse_errorinfo_header(_sip_header_t *sip_header,
3362882Svi117747     sip_parsed_header_t **header)
3372882Svi117747 {
3382882Svi117747 	return (sip_parse_hdr_parser3(sip_header, header, SIP_STR_VAL, B_TRUE));
3392882Svi117747 }
3402882Svi117747 
3412882Svi117747 /*
3422882Svi117747  * Expires = "Expires" HCOLON delta-seconds
3432882Svi117747  */
3442882Svi117747 int
sip_parse_expire_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)3452882Svi117747 sip_parse_expire_header(_sip_header_t *sip_header,
3462882Svi117747     sip_parsed_header_t **header)
3472882Svi117747 {
3482882Svi117747 	return (sip_parse_hdr_parser2(sip_header, header, SIP_INT_VAL));
3492882Svi117747 }
3502882Svi117747 
3512882Svi117747 /*
3522882Svi117747  * In-Reply-To = "In-Reply-To" HCOLON callid *(COMMA callid)
3532882Svi117747  */
3542882Svi117747 int
sip_parse_inreplyto_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)3552882Svi117747 sip_parse_inreplyto_header(_sip_header_t *sip_header,
3562882Svi117747     sip_parsed_header_t **header)
3572882Svi117747 {
3582882Svi117747 	return (sip_parse_hdr_parser1(sip_header, header, (char)NULL));
3592882Svi117747 }
3602882Svi117747 
3612882Svi117747 /*
3622882Svi117747  * RSeq = "RSeq" HCOLON response-num
3632882Svi117747  */
3642882Svi117747 int
sip_parse_rseq(_sip_header_t * sip_header,sip_parsed_header_t ** header)3652882Svi117747 sip_parse_rseq(_sip_header_t *sip_header, sip_parsed_header_t **header)
3662882Svi117747 {
3672882Svi117747 	int		r;
3682882Svi117747 	sip_hdr_value_t	*rseq_value;
3692882Svi117747 
3702882Svi117747 	r = sip_parse_hdr_parser2(sip_header, header, SIP_INT_VAL);
3712882Svi117747 	/*
3722882Svi117747 	 * Additionally, a value of 0 is bad_value
3732882Svi117747 	 */
3742882Svi117747 	if (sip_header->sip_hdr_parsed != NULL &&
3752882Svi117747 	    sip_header->sip_hdr_parsed->value != NULL) {
3762882Svi117747 		rseq_value = (sip_hdr_value_t *)
3772882Svi117747 		    sip_header->sip_hdr_parsed->value;
3782882Svi117747 		if (rseq_value->int_val == 0)
3792882Svi117747 			rseq_value->sip_value_state = SIP_VALUE_BAD;
3802882Svi117747 	}
3812882Svi117747 	return (r);
3822882Svi117747 }
3832882Svi117747 
3842882Svi117747 /*
3852882Svi117747  * Min-Expires  =  "Min-Expires" HCOLON delta-seconds
3862882Svi117747  */
3872882Svi117747 int
sip_parse_minexpire_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)3882882Svi117747 sip_parse_minexpire_header(_sip_header_t *sip_header,
3892882Svi117747     sip_parsed_header_t **header)
3902882Svi117747 {
3912882Svi117747 	return (sip_parse_hdr_parser2(sip_header, header, SIP_INT_VAL));
3922882Svi117747 }
3932882Svi117747 
3942882Svi117747 /*
3952882Svi117747  * MIME-Version = "MIME-Version" HCOLON 1*DIGIT "." 1*DIGIT
3962882Svi117747  */
3972882Svi117747 int
sip_parse_mimeversion_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)3982882Svi117747 sip_parse_mimeversion_header(_sip_header_t *sip_header,
3992882Svi117747     sip_parsed_header_t **header)
4002882Svi117747 {
4012882Svi117747 	return (sip_parse_hdr_parser4(sip_header, header));
4022882Svi117747 }
4032882Svi117747 
4042882Svi117747 /*
4052882Svi117747  * Organization = "Organization" HCOLON [TEXT-UTF8-TRIM]
4062882Svi117747  */
4072882Svi117747 int
sip_parse_org_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)4082882Svi117747 sip_parse_org_header(_sip_header_t *sip_header,
4092882Svi117747     sip_parsed_header_t **header)
4102882Svi117747 {
4112882Svi117747 	if (sip_is_empty_hdr(sip_header))
4122882Svi117747 		return (sip_parse_hdr_empty(sip_header, header));
4132882Svi117747 	return (sip_parse_hdr_parser4(sip_header, header));
4142882Svi117747 }
4152882Svi117747 
4162882Svi117747 /*
4172882Svi117747  * Priority = "Priority" HCOLON priority-val
4182882Svi117747  * priority-val = "emergency" | "urgent" | "normal" | "non-urgent" | other
4192882Svi117747  * other = token
4202882Svi117747  */
4212882Svi117747 int
sip_parse_priority_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)4222882Svi117747 sip_parse_priority_header(_sip_header_t *sip_header,
4232882Svi117747     sip_parsed_header_t **header)
4242882Svi117747 {
4252882Svi117747 	return (sip_parse_hdr_parser4(sip_header, header));
4262882Svi117747 }
4272882Svi117747 
4282882Svi117747 /*
4292882Svi117747  * Reply-To = "Reply-To" HCOLON rplyto-spec
4302882Svi117747  * rplyto-spec = (name-addr | addr-spec) *(SEMI rplyto-param)
4312882Svi117747  * rplyto-param = generic-param
4322882Svi117747  * name-addr = [ display-name ] LAQUOT addr-spec RAQUOT
4332882Svi117747  * addr-spec = SIP-URI | SIPS-URI | absolute URI
4342882Svi117747  */
4352882Svi117747 int
sip_parse_replyto_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)4362882Svi117747 sip_parse_replyto_header(_sip_header_t *sip_header,
4372882Svi117747     sip_parsed_header_t **header)
4382882Svi117747 {
4392882Svi117747 	return (sip_parse_hdr_parser3(sip_header, header, SIP_STRS_VAL,
4402882Svi117747 	    B_TRUE));
4412882Svi117747 }
4422882Svi117747 
4432882Svi117747 /*
4442882Svi117747  * PRIVACY = "Privacy" HCOLON priv-value *(COMMA priv-value)
4452882Svi117747  * priv-value   =   "header" / "session" / "user" / "none" / "critical"
4462882Svi117747  *                  / token / id
4472882Svi117747  */
4482882Svi117747 int
sip_parse_privacy_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)4492882Svi117747 sip_parse_privacy_header(_sip_header_t *sip_header,
4502882Svi117747     sip_parsed_header_t **header)
4512882Svi117747 {
4522882Svi117747 	return (sip_parse_hdr_parser1(sip_header, header, (char)NULL));
4532882Svi117747 }
4542882Svi117747 
4552882Svi117747 
4562882Svi117747 /*
4572882Svi117747  * Require = "Require" HCOLON option-tag * (COMMA option-tag)
4582882Svi117747  */
4592882Svi117747 int
sip_parse_require_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)4602882Svi117747 sip_parse_require_header(_sip_header_t *sip_header,
4612882Svi117747     sip_parsed_header_t **header)
4622882Svi117747 {
4632882Svi117747 	return (sip_parse_hdr_parser1(sip_header, header, (char)NULL));
4642882Svi117747 }
4652882Svi117747 
4662882Svi117747 /*
4672882Svi117747  * Retry-After = "Retry-After" HCOLON delta-seconds [ comment ] *
4682882Svi117747  *		(SEMI retry-param)
4692882Svi117747  * retry-param = "duration" EQUAL delta-seconds
4702882Svi117747  */
4712882Svi117747 int
sip_parse_retryaft_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)4722882Svi117747 sip_parse_retryaft_header(_sip_header_t *sip_header,
4732882Svi117747     sip_parsed_header_t **header)
4742882Svi117747 {
4752882Svi117747 	sip_parsed_header_t	*parsed_header;
4762882Svi117747 	sip_hdr_value_t		*value = NULL;
4772882Svi117747 	int			ret;
4782882Svi117747 
4792882Svi117747 	if ((ret = sip_prim_parsers(sip_header, header)) != 0)
4802882Svi117747 		return (ret);
4812882Svi117747 
4822882Svi117747 	if (*header != NULL)
4832882Svi117747 		return (0);
4842882Svi117747 
4852882Svi117747 	parsed_header = calloc(1, sizeof (sip_parsed_header_t));
4862882Svi117747 	if (parsed_header == NULL)
4872882Svi117747 		return (ENOMEM);
4882882Svi117747 	parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1;
4892882Svi117747 	parsed_header->sip_header = sip_header;
4902882Svi117747 
4912882Svi117747 	value = calloc(1, sizeof (sip_hdr_value_t));
4922882Svi117747 	if (value == NULL) {
4932882Svi117747 		sip_free_phdr(parsed_header);
4942882Svi117747 		return (ENOMEM);
4952882Svi117747 	}
4962882Svi117747 
4972882Svi117747 	parsed_header->value = (sip_value_t *)value;
4982882Svi117747 	value->sip_value_start = sip_header->sip_hdr_current;
4992882Svi117747 	value->sip_value_header = parsed_header;
5002882Svi117747 
5012882Svi117747 	ret = sip_atoi(sip_header, &(value->intstr_int));
5022882Svi117747 	if (ret != 0)
5032882Svi117747 		value->sip_value_state = SIP_VALUE_BAD;
5042882Svi117747 	if (sip_find_token(sip_header, SIP_LPAR) == 0) {
5052882Svi117747 		value->intstr_str_ptr = sip_header->sip_hdr_current;
5062882Svi117747 		if (sip_find_token(sip_header, SIP_RPAR) == 0) {
5072882Svi117747 			value->intstr_str_len =
5082882Svi117747 			    sip_header->sip_hdr_current -
509*5092Sgm209912 			    value->intstr_str_ptr - 1;
5102882Svi117747 			if (sip_find_token(sip_header, SIP_SEMI) == 0) {
5112882Svi117747 				sip_header->sip_hdr_current--;
5122882Svi117747 				(void) sip_parse_params(sip_header,
5132882Svi117747 				    &(value->sip_param_list));
5142882Svi117747 			}
5152882Svi117747 		} else {
5162882Svi117747 			value->sip_value_state = SIP_VALUE_BAD;
5172882Svi117747 			return (EPROTO);
5182882Svi117747 		}
5192882Svi117747 	} else {
5202882Svi117747 		value->intstr_str_ptr = NULL;
5212882Svi117747 		value->intstr_str_len = 0;
5222882Svi117747 
5232882Svi117747 		/*
5242882Svi117747 		 * from value start, search if parameter list
5252882Svi117747 		 */
5262882Svi117747 		sip_header->sip_hdr_current = value->sip_value_start;
5272882Svi117747 		if (sip_find_token(sip_header, SIP_SEMI) == 0) {
5282882Svi117747 			sip_header->sip_hdr_current--;
5292882Svi117747 			(void) sip_parse_params(sip_header,
5302882Svi117747 			    &(value->sip_param_list));
5312882Svi117747 		}
5322882Svi117747 	}
5332882Svi117747 
5342882Svi117747 	*header = parsed_header;
5352882Svi117747 	sip_header->sip_hdr_parsed = *header;
5362882Svi117747 	return (0);
5372882Svi117747 }
5382882Svi117747 
5392882Svi117747 /*
5402882Svi117747  * Server = "Server" HCOLON servel-val *(LWS server-val)
5412882Svi117747  * servel-val = product|comment
5422882Svi117747  * product = token [SLASH version]
5432882Svi117747  * version = token
5442882Svi117747  * Treated as one single string
5452882Svi117747  */
5462882Svi117747 int
sip_parse_server_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)5472882Svi117747 sip_parse_server_header(_sip_header_t *sip_header, sip_parsed_header_t **header)
5482882Svi117747 {
5492882Svi117747 	return (sip_parse_hdr_parser4(sip_header, header));
5502882Svi117747 }
5512882Svi117747 
5522882Svi117747 /*
5532882Svi117747  * Subject = ("Subject" | "s")HCOLON [TEXT-UTF8-TRIM]
5542882Svi117747  */
5552882Svi117747 int
sip_parse_subject_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)5562882Svi117747 sip_parse_subject_header(_sip_header_t *sip_header,
5572882Svi117747     sip_parsed_header_t **header)
5582882Svi117747 {
5592882Svi117747 	if (sip_is_empty_hdr(sip_header))
5602882Svi117747 		return (sip_parse_hdr_empty(sip_header, header));
5612882Svi117747 	return (sip_parse_hdr_parser4(sip_header, header));
5622882Svi117747 }
5632882Svi117747 
5642882Svi117747 /*
5652882Svi117747  * Supported = ("Supported" | "k") HCOLON [option-tag * (COMMA option-tag) ]
5662882Svi117747  */
5672882Svi117747 int
sip_parse_support_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)5682882Svi117747 sip_parse_support_header(_sip_header_t *sip_header,
5692882Svi117747     sip_parsed_header_t **header)
5702882Svi117747 {
5712882Svi117747 	if (sip_is_empty_hdr(sip_header))
5722882Svi117747 		return (sip_parse_hdr_empty(sip_header, header));
5732882Svi117747 	return (sip_parse_hdr_parser1(sip_header, header, (char)NULL));
5742882Svi117747 }
5752882Svi117747 
5762882Svi117747 /*
5772882Svi117747  * Timestamp = "Timestamp" HCOLON 1*DIGIT ["." *(DIGIT)] [LWS delay]
5782882Svi117747  */
5792882Svi117747 int
sip_parse_timestamp_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)5802882Svi117747 sip_parse_timestamp_header(_sip_header_t *sip_header,
5812882Svi117747     sip_parsed_header_t **header)
5822882Svi117747 {
5832882Svi117747 	sip_parsed_header_t	*parsed_header;
5842882Svi117747 	sip_hdr_value_t		*value = NULL;
5852882Svi117747 	int			ret;
5862882Svi117747 
5872882Svi117747 	if ((ret = sip_prim_parsers(sip_header, header)) != 0)
5882882Svi117747 		return (ret);
5892882Svi117747 
5902882Svi117747 	if (*header != NULL)
5912882Svi117747 		return (0);
5922882Svi117747 
5932882Svi117747 	parsed_header = calloc(1, sizeof (sip_parsed_header_t));
5942882Svi117747 	if (parsed_header == NULL)
5952882Svi117747 		return (ENOMEM);
5962882Svi117747 	parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1;
5972882Svi117747 	parsed_header->sip_header = sip_header;
5982882Svi117747 
5992882Svi117747 	value = calloc(1, sizeof (sip_hdr_value_t));
6002882Svi117747 	if (value == NULL) {
6012882Svi117747 		sip_free_phdr(parsed_header);
6022882Svi117747 		return (ENOMEM);
6032882Svi117747 	}
6042882Svi117747 	parsed_header->value = (sip_value_t *)value;
6052882Svi117747 
6062882Svi117747 	value->sip_value_start = sip_header->sip_hdr_current;
6072882Svi117747 	value->sip_value_header = parsed_header;
6082882Svi117747 
6092882Svi117747 	if (sip_skip_white_space(sip_header) != 0) {
6102882Svi117747 		value->sip_value_state = SIP_VALUE_BAD;
6112882Svi117747 		return (EPROTO);
6122882Svi117747 	}
6132882Svi117747 	value->strs1_val_ptr = sip_header->sip_hdr_current;
6142882Svi117747 
6152882Svi117747 	if (sip_find_white_space(sip_header) == 0) {
6162882Svi117747 		/*
6172882Svi117747 		 * timestamp and delay, timestamp in str1, delay in str2
6182882Svi117747 		 */
6192882Svi117747 		value->strs1_val_len = sip_header->sip_hdr_current -
6202882Svi117747 		    value->strs1_val_ptr;
6212882Svi117747 		(void) sip_skip_white_space(sip_header);
6222882Svi117747 
6232882Svi117747 		value->strs2_val_ptr = sip_header->sip_hdr_current;
6242882Svi117747 		if (sip_find_cr(sip_header) != 0) {
6252882Svi117747 			value->sip_value_state = SIP_VALUE_BAD;
6262882Svi117747 			return (EPROTO);
6272882Svi117747 		}
6282882Svi117747 		if (sip_header->sip_hdr_current < value->strs2_val_ptr) {
6292882Svi117747 			value->strs2_val_ptr = NULL;
6302882Svi117747 			value->strs2_val_len = 0;
6312882Svi117747 		} else {
6322882Svi117747 			value->strs2_val_len = sip_header->sip_hdr_current -
6332882Svi117747 			    value->strs2_val_ptr;
6342882Svi117747 		}
6352882Svi117747 	} else {
6362882Svi117747 		/*
6372882Svi117747 		 * no delay information
6382882Svi117747 		 */
6392882Svi117747 		value->strs1_val_len = sip_header->sip_hdr_current
6402882Svi117747 		    - value->strs1_val_ptr;
6412882Svi117747 		value->strs2_val_ptr = NULL;
6422882Svi117747 		value->strs2_val_len = 0;
6432882Svi117747 	}
6442882Svi117747 
6452882Svi117747 	*header = parsed_header;
6462882Svi117747 	sip_header->sip_hdr_parsed = *header;
6472882Svi117747 
6482882Svi117747 	return (0);
6492882Svi117747 }
6502882Svi117747 /*
6512882Svi117747  * Unsupported = "Unsupported" HCOLON option-tag * (COMMA option-tag)
6522882Svi117747  */
6532882Svi117747 int
sip_parse_usupport_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)6542882Svi117747 sip_parse_usupport_header(_sip_header_t *sip_header,
6552882Svi117747     sip_parsed_header_t **header)
6562882Svi117747 {
6572882Svi117747 	return (sip_parse_hdr_parser1(sip_header, header, (char)NULL));
6582882Svi117747 }
6592882Svi117747 
6602882Svi117747 /*
6612882Svi117747  * User-Agent = "User-Agent" HCOLON server-val * (LWS server-val)
6622882Svi117747  * servel-val = product |comment
6632882Svi117747  * product = token [SLASH version]
6642882Svi117747  * version = token
6652882Svi117747  */
6662882Svi117747 int
sip_parse_useragt_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)6672882Svi117747 sip_parse_useragt_header(_sip_header_t *sip_header,
6682882Svi117747     sip_parsed_header_t **header)
6692882Svi117747 {
6702882Svi117747 	return (sip_parse_hdr_parser4(sip_header, header));
6712882Svi117747 }
6722882Svi117747 
6732882Svi117747 /*
6742882Svi117747  * Warning = "Warning" HCOLON warning-value *(COMMA warning-value)
6752882Svi117747  * warning-value = warn-code SP warn-agent SP warn-text
6762882Svi117747  * warn-code = 3DIGIT
6772882Svi117747  * warn-agent = hostport | pseudonym ;
6782882Svi117747  *		 the name or pseudonym of the server adding;
6792882Svi117747  *		 the Warning header, for use in debugging
6802882Svi117747  * warn-text = quoted-string
6812882Svi117747  * pseudonym = token
6822882Svi117747  */
6832882Svi117747 int
sip_parse_warn_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)6842882Svi117747 sip_parse_warn_header(_sip_header_t *sip_header, sip_parsed_header_t **header)
6852882Svi117747 {
6862882Svi117747 	sip_parsed_header_t	*parsed_header;
6872882Svi117747 	int			ret;
6882882Svi117747 	sip_hdr_value_t		*value = NULL;
6892882Svi117747 	sip_hdr_value_t		*last_value = NULL;
6902882Svi117747 
6912882Svi117747 	if ((ret = sip_prim_parsers(sip_header, header)) != 0)
6922882Svi117747 		return (ret);
6932882Svi117747 
6942882Svi117747 	if (*header != NULL)
6952882Svi117747 		return (0);
6962882Svi117747 
6972882Svi117747 	parsed_header = calloc(1, sizeof (sip_parsed_header_t));
6982882Svi117747 	if (parsed_header == NULL)
6992882Svi117747 		return (ENOMEM);
7002882Svi117747 	parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1;
7012882Svi117747 	parsed_header->sip_header = sip_header;
7022882Svi117747 
7032882Svi117747 	while (sip_header->sip_hdr_current < sip_header->sip_hdr_end) {
7042882Svi117747 		value = calloc(1, sizeof (sip_hdr_value_t));
7052882Svi117747 		if (value == NULL) {
7062882Svi117747 			sip_free_phdr(parsed_header);
7072882Svi117747 			return (ENOMEM);
7082882Svi117747 		}
7092882Svi117747 
7102882Svi117747 		if (last_value != NULL)
7112882Svi117747 			last_value->sip_next_value = value;
7122882Svi117747 		else
7132882Svi117747 			parsed_header->value = (sip_value_t *)value;
7142882Svi117747 
7152882Svi117747 		value->sip_value_start = sip_header->sip_hdr_current;
7162882Svi117747 		value->sip_value_header = parsed_header;
7172882Svi117747 
7182882Svi117747 		ret = sip_atoi(sip_header, &value->warn_code);
7192882Svi117747 		if (ret != 0 || value->warn_code < 100 ||
7202882Svi117747 		    value->warn_code > 999) {
7212882Svi117747 			value->sip_value_state = SIP_VALUE_BAD;
7222882Svi117747 			goto get_next_val;
7232882Svi117747 		}
7242882Svi117747 		if (sip_skip_white_space(sip_header) != 0) {
7252882Svi117747 			value->sip_value_state = SIP_VALUE_BAD;
7262882Svi117747 			goto get_next_val;
7272882Svi117747 		}
7282882Svi117747 		value->warn_agt_ptr = sip_header->sip_hdr_current;
7292882Svi117747 
7302882Svi117747 		if (sip_find_token(sip_header, SIP_QUOTE) == 0) {
7312882Svi117747 			/*
7322882Svi117747 			 * get warning agent
7332882Svi117747 			 */
7342882Svi117747 			sip_header->sip_hdr_current--;
7352882Svi117747 			(void) sip_reverse_skip_white_space(sip_header);
7362882Svi117747 			value->warn_agt_len = sip_header->sip_hdr_current -
7372882Svi117747 			    value->warn_agt_ptr - 1;
7382882Svi117747 			if (value->warn_agt_len <= 0) {
7392882Svi117747 				value->warn_agt_ptr = NULL;
7402882Svi117747 				value->sip_value_state = SIP_VALUE_BAD;
7412882Svi117747 			}
7422882Svi117747 
7432882Svi117747 			/*
7442882Svi117747 			 * We will have a  SIP_QUOTE here
7452882Svi117747 			 */
7462882Svi117747 			(void) sip_find_token(sip_header, SIP_QUOTE);
7472882Svi117747 
7482882Svi117747 			value->warn_text_ptr =  sip_header->sip_hdr_current;
7492882Svi117747 			if (sip_find_token(sip_header, SIP_QUOTE) == 0) {
7502882Svi117747 				value->warn_text_len =
7512882Svi117747 				    sip_header->sip_hdr_current -
752*5092Sgm209912 				    value->warn_text_ptr - 1;
7532882Svi117747 			} else {
7542882Svi117747 				value->sip_value_state = SIP_VALUE_BAD;
7552882Svi117747 				goto get_next_val;
7562882Svi117747 			}
7572882Svi117747 		} else
7582882Svi117747 			/*
7592882Svi117747 			 * warning text must present
7602882Svi117747 			 */
7612882Svi117747 			value->sip_value_state = SIP_VALUE_BAD;
7622882Svi117747 
7632882Svi117747 get_next_val:
7642882Svi117747 		if (sip_find_token(sip_header, SIP_COMMA) != 0)
7652882Svi117747 			break;
7662882Svi117747 		value->sip_value_end = sip_header->sip_hdr_current - 1;
7672882Svi117747 		last_value = value;
7682882Svi117747 		(void) sip_skip_white_space(sip_header);
7692882Svi117747 	}
7702882Svi117747 
7712882Svi117747 	*header = parsed_header;
7722882Svi117747 
7732882Svi117747 	sip_header->sip_hdr_parsed = *header;
7742882Svi117747 	return (0);
7752882Svi117747 }
7762882Svi117747 
7772882Svi117747 /*
7782882Svi117747  * Parse RAck header
7792882Svi117747  * "RAck" HCOLON response-num LWS CSeq-num LWS Method
7802882Svi117747  * response-num  =  1*DIGIT
7812882Svi117747  * CSeq-num      =  1*DIGIT
7822882Svi117747  */
7832882Svi117747 int
sip_parse_rack(_sip_header_t * sip_header,sip_parsed_header_t ** header)7842882Svi117747 sip_parse_rack(_sip_header_t *sip_header, sip_parsed_header_t **header)
7852882Svi117747 {
7862882Svi117747 	sip_parsed_header_t	*parsed_header;
7872882Svi117747 	sip_hdr_value_t		*rack_value;
7882882Svi117747 	int			len;
7892882Svi117747 	char			*tmp_ptr;
7902882Svi117747 	int			i;
7912882Svi117747 	int			ret;
7922882Svi117747 
7932882Svi117747 	if ((ret = sip_prim_parsers(sip_header, header)) != 0)
7942882Svi117747 		return (ret);
7952882Svi117747 
7962882Svi117747 	if (*header != NULL)
7972882Svi117747 		return (0);
7982882Svi117747 
7992882Svi117747 	parsed_header = calloc(1, sizeof (sip_parsed_header_t));
8002882Svi117747 	if (parsed_header == NULL)
8012882Svi117747 		return (ENOMEM);
8022882Svi117747 	parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1;
8032882Svi117747 	parsed_header->sip_header = sip_header;
8042882Svi117747 
8052882Svi117747 	parsed_header->value =  calloc(1, sizeof (sip_hdr_value_t));
8062882Svi117747 	if (parsed_header->value == NULL) {
8072882Svi117747 		free(parsed_header);
8082882Svi117747 		return (ENOMEM);
8092882Svi117747 	}
8102882Svi117747 	rack_value = (sip_hdr_value_t *)parsed_header->value;
8112882Svi117747 	rack_value->sip_value_version = SIP_VALUE_VERSION_1;
8122882Svi117747 	rack_value->sip_value_start = sip_header->sip_hdr_current;
8132882Svi117747 	rack_value->sip_value_header = parsed_header;
8142882Svi117747 	if (sip_atoi(sip_header, &rack_value->rack_resp) ||
8152882Svi117747 	    rack_value->rack_resp == 0) {
8162882Svi117747 		rack_value->sip_value_state = SIP_VALUE_BAD;
8172882Svi117747 		rack_value->sip_value_end = sip_header->sip_hdr_end - 2;
8182882Svi117747 		goto rack_parse_done;
8192882Svi117747 	}
8202882Svi117747 	rack_value->sip_value_header = parsed_header;
8212882Svi117747 	/*
8222882Svi117747 	 * Get cseq.
8232882Svi117747 	 */
8242882Svi117747 	if (sip_skip_white_space(sip_header) != 0) {
8252882Svi117747 		rack_value->sip_value_state = SIP_VALUE_BAD;
8262882Svi117747 		rack_value->sip_value_end = sip_header->sip_hdr_end - 2;
8272882Svi117747 		goto rack_parse_done;
8282882Svi117747 	}
8292882Svi117747 	if (sip_atoi(sip_header, &rack_value->rack_cseq)) {
8302882Svi117747 		rack_value->sip_value_state = SIP_VALUE_BAD;
8312882Svi117747 		rack_value->sip_value_end = sip_header->sip_hdr_end - 2;
8322882Svi117747 		goto rack_parse_done;
8332882Svi117747 	}
8342882Svi117747 	/*
8352882Svi117747 	 * Get method.
8362882Svi117747 	 */
8372882Svi117747 	if (sip_skip_white_space(sip_header) != 0) {
8382882Svi117747 		rack_value->sip_value_state = SIP_VALUE_BAD;
8392882Svi117747 		rack_value->sip_value_end = sip_header->sip_hdr_end - 2;
8402882Svi117747 		goto rack_parse_done;
8412882Svi117747 	}
8422882Svi117747 
8432882Svi117747 	tmp_ptr = sip_header->sip_hdr_current;
8442882Svi117747 	if (sip_find_white_space(sip_header)) {
8452882Svi117747 		rack_value->sip_value_state = SIP_VALUE_BAD;
8462882Svi117747 		rack_value->sip_value_end = sip_header->sip_hdr_end - 2;
8472882Svi117747 		goto rack_parse_done;
8482882Svi117747 	}
8492882Svi117747 
8502882Svi117747 	len = sip_header->sip_hdr_current - tmp_ptr;
8512882Svi117747 
8522882Svi117747 	for (i = 1; i < MAX_SIP_METHODS; i++) {
8532882Svi117747 		if (strncmp(sip_methods[i].name, tmp_ptr, len) == 0)
8542882Svi117747 			break;
8552882Svi117747 	}
8562882Svi117747 
8572882Svi117747 	if (i >= MAX_SIP_METHODS) {
8582882Svi117747 		rack_value->sip_value_state = SIP_VALUE_BAD;
8592882Svi117747 		rack_value->sip_value_end = sip_header->sip_hdr_end - 2;
8602882Svi117747 		goto rack_parse_done;
8612882Svi117747 	}
8622882Svi117747 
8632882Svi117747 	rack_value->rack_method = i;
8642882Svi117747 	rack_value->sip_value_end = sip_header->sip_hdr_current;
8652882Svi117747 
8662882Svi117747 rack_parse_done:
8672882Svi117747 	sip_header->sip_hdr_parsed = parsed_header;
8682882Svi117747 
8692882Svi117747 	*header = parsed_header;
8702882Svi117747 	return (0);
8712882Svi117747 }
8722882Svi117747 
8732882Svi117747 /*
8742882Svi117747  * Allow  =  "Allow" HCOLON [Method *(COMMA Method)]
8752882Svi117747  */
8762882Svi117747 int
sip_parse_allow_events_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)8772882Svi117747 sip_parse_allow_events_header(_sip_header_t *sip_header,
8782882Svi117747     sip_parsed_header_t **header)
8792882Svi117747 {
8802882Svi117747 	return (sip_parse_hdr_parser1(sip_header, header, (char)NULL));
8812882Svi117747 }
8822882Svi117747 
8832882Svi117747 /*
8842882Svi117747  * Event             =  ( "Event" / "o" ) HCOLON event-type
8852882Svi117747  *			*( SEMI event-param )
8862882Svi117747  * event-type        =  event-package *( "." event-template )
8872882Svi117747  * event-package     =  token-nodot
8882882Svi117747  * event-template    =  token-nodot
8892882Svi117747  * token-nodot       =  1*( alphanum / "-"  / "!" / "%" / "*"
8902882Svi117747  *			/ "_" / "+" / "`" / "'" / "~" )
8912882Svi117747  * event-param       =  generic-param / ( "id" EQUAL token )
8922882Svi117747  */
8932882Svi117747 int
sip_parse_event_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)8942882Svi117747 sip_parse_event_header(_sip_header_t *sip_header, sip_parsed_header_t **header)
8952882Svi117747 {
8962882Svi117747 	return (sip_parse_hdr_parser1(sip_header, header, (char)NULL));
8972882Svi117747 }
8982882Svi117747 
8992882Svi117747 /*
9002882Svi117747  * Subscription-State   = "Subscription-State" HCOLON substate-value
9012882Svi117747  * 			*( SEMI subexp-params )
9022882Svi117747  * substate-value       = "active" / "pending" / "terminated"
9032882Svi117747  *			/ extension-substate
9042882Svi117747  * extension-substate   = token
9052882Svi117747  * subexp-params        =   ("reason" EQUAL event-reason-value)
9062882Svi117747  *			/ ("expires" EQUAL delta-seconds)*
9072882Svi117747  * 			/ ("retry-after" EQUAL delta-seconds)
9082882Svi117747  *			/ generic-param
9092882Svi117747  * event-reason-value   =   "deactivated"
9102882Svi117747  *				/ "probation"
9112882Svi117747  *				/ "rejected"
9122882Svi117747  *				/ "timeout"
9132882Svi117747  *				/ "giveup"
9142882Svi117747  *				/ "noresource"
9152882Svi117747  *				/ event-reason-extension
9162882Svi117747  * event-reason-extension = token
9172882Svi117747  */
9182882Svi117747 int
sip_parse_substate_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)9192882Svi117747 sip_parse_substate_header(_sip_header_t *sip_header,
9202882Svi117747     sip_parsed_header_t **header)
9212882Svi117747 {
9222882Svi117747 	return (sip_parse_hdr_parser1(sip_header, header, (char)NULL));
9232882Svi117747 }
9242882Svi117747 
9252882Svi117747 /*
9262882Svi117747  * Authorization     =  "Authorization" HCOLON credentials
9272882Svi117747  * credentials       =  ("Digest" LWS digest-response)
9282882Svi117747  *			/ other-response
9292882Svi117747  * digest-response   =  dig-resp *(COMMA dig-resp)
9302882Svi117747  * dig-resp          =  username / realm / nonce / digest-uri
9312882Svi117747  *			/ dresponse / algorithm / cnonce
9322882Svi117747  *			/ opaque / message-qop
9332882Svi117747  *			/ nonce-count / auth-param
9342882Svi117747  * username          =  "username" EQUAL username-value
9352882Svi117747  * username-value    =  quoted-string
9362882Svi117747  * digest-uri        =  "uri" EQUAL LDQUOT digest-uri-value RDQUOT
9372882Svi117747  * digest-uri-value  =  rquest-uri ; Equal to request-uri as specified
9382882Svi117747  *			by HTTP/1.1
9392882Svi117747  * message-qop       =  "qop" EQUAL qop-value
9402882Svi117747  * cnonce            =  "cnonce" EQUAL cnonce-value
9412882Svi117747  * cnonce-value      =  nonce-value
9422882Svi117747  * nonce-count       =  "nc" EQUAL nc-value
9432882Svi117747  * nc-value          =  8LHEX
9442882Svi117747  * dresponse         =  "response" EQUAL request-digest
9452882Svi117747  * request-digest    =  LDQUOT 32LHEX RDQUOT
9462882Svi117747  * auth-param        =  auth-param-name EQUAL
9472882Svi117747  * 			( token / quoted-string )
9482882Svi117747  * auth-param-name   =  token
9492882Svi117747  * other-response    =  auth-scheme LWS auth-param
9502882Svi117747  *			*(COMMA auth-param)
9512882Svi117747  * auth-scheme       =  token
9522882Svi117747  */
9532882Svi117747 int
sip_parse_author_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)9542882Svi117747 sip_parse_author_header(_sip_header_t *sip_header,
9552882Svi117747     sip_parsed_header_t **header)
9562882Svi117747 {
9572882Svi117747 	return (sip_parse_hdr_parser5(sip_header, header, B_TRUE));
9582882Svi117747 }
9592882Svi117747 
9602882Svi117747 /*
9612882Svi117747  * Authentication-Info  =  "Authentication-Info" HCOLON ainfo
9622882Svi117747  *				*(COMMA ainfo)
9632882Svi117747  * ainfo                =  nextnonce / message-qop
9642882Svi117747  *				/ response-auth / cnonce
9652882Svi117747  *				/ nonce-count
9662882Svi117747  * nextnonce            =  "nextnonce" EQUAL nonce-value
9672882Svi117747  * response-auth        =  "rspauth" EQUAL response-digest
9682882Svi117747  * response-digest      =  LDQUOT *LHEX RDQUOT
9692882Svi117747  *
9702882Svi117747  */
9712882Svi117747 int
sip_parse_ainfo_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)9722882Svi117747 sip_parse_ainfo_header(_sip_header_t *sip_header,
9732882Svi117747     sip_parsed_header_t **header)
9742882Svi117747 {
9752882Svi117747 	return (sip_parse_hdr_parser1(sip_header, header, (char)NULL));
9762882Svi117747 }
9772882Svi117747 
9782882Svi117747 /*
9792882Svi117747  * Proxy-Authenticate  =  "Proxy-Authenticate" HCOLON challenge
9802882Svi117747  * challenge           =  ("Digest" LWS digest-cln *(COMMA digest-cln))
9812882Svi117747  *				/ other-challenge
9822882Svi117747  * other-challenge     =  auth-scheme LWS auth-param
9832882Svi117747  * 				*(COMMA auth-param)
9842882Svi117747  * digest-cln          =  realm / domain / nonce
9852882Svi117747  *				/ opaque / stale / algorithm
9862882Svi117747  *				/ qop-options / auth-param
9872882Svi117747  * realm               =  "realm" EQUAL realm-value
9882882Svi117747  * realm-value         =  quoted-string
9892882Svi117747  * domain              =  "domain" EQUAL LDQUOT URI
9902882Svi117747  *				*( 1*SP URI ) RDQUOT
9912882Svi117747  * URI                 =  absoluteURI / abs-path
9922882Svi117747  * nonce               =  "nonce" EQUAL nonce-value
9932882Svi117747  * nonce-value         =  quoted-string
9942882Svi117747  * opaque              =  "opaque" EQUAL quoted-string
9952882Svi117747  * stale               =  "stale" EQUAL ( "true" / "false" )
9962882Svi117747  * algorithm           =  "algorithm" EQUAL ( "MD5" / "MD5-sess"
9972882Svi117747  *			/ token )
9982882Svi117747  * qop-options         =  "qop" EQUAL LDQUOT qop-value
9992882Svi117747  *			*("," qop-value) RDQUOT
10002882Svi117747  * qop-value           =  "auth" / "auth-int" / token
10012882Svi117747  *
10022882Svi117747  */
10032882Svi117747 int
sip_parse_pauthen_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)10042882Svi117747 sip_parse_pauthen_header(_sip_header_t *sip_header,
10052882Svi117747     sip_parsed_header_t **header)
10062882Svi117747 {
10072882Svi117747 	return (sip_parse_hdr_parser5(sip_header, header, B_TRUE));
10082882Svi117747 }
10092882Svi117747 
10102882Svi117747 /*
10112882Svi117747  * Proxy-Authorization  =  "Proxy-Authorization" HCOLON credentials
10122882Svi117747  */
10132882Svi117747 int
sip_parse_pauthor_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)10142882Svi117747 sip_parse_pauthor_header(_sip_header_t *sip_header,
10152882Svi117747     sip_parsed_header_t **header)
10162882Svi117747 {
10172882Svi117747 	return (sip_parse_hdr_parser5(sip_header, header, B_TRUE));
10182882Svi117747 }
10192882Svi117747 
10202882Svi117747 /*
10212882Svi117747  * Proxy-Require  =  "Proxy-Require" HCOLON option-tag
10222882Svi117747  *			*(COMMA option-tag)
10232882Svi117747  * option-tag     =  token
10242882Svi117747  */
10252882Svi117747 int
sip_parse_preq_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)10262882Svi117747 sip_parse_preq_header(_sip_header_t *sip_header,
10272882Svi117747     sip_parsed_header_t **header)
10282882Svi117747 {
10292882Svi117747 	return (sip_parse_hdr_parser1(sip_header, header, (char)NULL));
10302882Svi117747 }
10312882Svi117747 
10322882Svi117747 /*
10332882Svi117747  * WWW-Authenticate  =  "WWW-Authenticate" HCOLON challenge
10342882Svi117747  * extension-header  =  header-name HCOLON header-value
10352882Svi117747  * header-name       =  token
10362882Svi117747  * header-value      =  *(TEXT-UTF8char / UTF8-CONT / LWS)
10372882Svi117747  * message-body  =  *OCTET
10382882Svi117747  *
10392882Svi117747  */
10402882Svi117747 int
sip_parse_wauthen_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)10412882Svi117747 sip_parse_wauthen_header(_sip_header_t *sip_header,
10422882Svi117747     sip_parsed_header_t **header)
10432882Svi117747 {
10442882Svi117747 	return (sip_parse_hdr_parser5(sip_header, header, B_TRUE));
10452882Svi117747 }
10462882Svi117747 
10472882Svi117747 /*
10482882Svi117747  * Call-ID  =  ( "Call-ID" / "i" ) HCOLON callid
10492882Svi117747  */
10502882Svi117747 int
sip_parse_cid_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)10512882Svi117747 sip_parse_cid_header(_sip_header_t *sip_header, sip_parsed_header_t **header)
10522882Svi117747 {
10532882Svi117747 	return (sip_parse_hdr_parser4(sip_header, header));
10542882Svi117747 }
10552882Svi117747 
10562882Svi117747 /*
10572882Svi117747  * CSeq  =  "CSeq" HCOLON 1*DIGIT LWS Method
10582882Svi117747  */
10592882Svi117747 int
sip_parse_cseq_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)10602882Svi117747 sip_parse_cseq_header(_sip_header_t *sip_header, sip_parsed_header_t **header)
10612882Svi117747 {
10622882Svi117747 	sip_parsed_header_t	*parsed_header;
10632882Svi117747 	sip_hdr_value_t		*cseq_value;
10642882Svi117747 	int			len;
10652882Svi117747 	char			*tmp_ptr;
10662882Svi117747 	int			i;
10672882Svi117747 	int			ret;
10682882Svi117747 
10692882Svi117747 	if ((ret = sip_prim_parsers(sip_header, header)) != 0)
10702882Svi117747 		return (ret);
10712882Svi117747 
10722882Svi117747 	if (*header != NULL)
10732882Svi117747 		return (0);
10742882Svi117747 
10752882Svi117747 	parsed_header = calloc(1, sizeof (sip_parsed_header_t));
10762882Svi117747 	if (parsed_header == NULL)
10772882Svi117747 		return (ENOMEM);
10782882Svi117747 	parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1;
10792882Svi117747 	parsed_header->sip_header = sip_header;
10802882Svi117747 
10812882Svi117747 	parsed_header->value =  calloc(1, sizeof (sip_hdr_value_t));
10822882Svi117747 	if (parsed_header->value == NULL) {
10832882Svi117747 		free(parsed_header);
10842882Svi117747 		return (ENOMEM);
10852882Svi117747 	}
10862882Svi117747 	cseq_value = (sip_hdr_value_t *)parsed_header->value;
10872882Svi117747 	cseq_value->sip_value_version = SIP_VALUE_VERSION_1;
10882882Svi117747 	cseq_value->sip_value_start = sip_header->sip_hdr_current;
10892882Svi117747 	if (sip_atoi(sip_header, &cseq_value->cseq_num)) {
10902882Svi117747 		cseq_value->sip_value_state = SIP_VALUE_BAD;
10912882Svi117747 		cseq_value->sip_value_end = sip_header->sip_hdr_end - 2;
10922882Svi117747 		goto cseq_parse_done;
10932882Svi117747 	}
10942882Svi117747 	cseq_value->sip_value_header = parsed_header;
10952882Svi117747 	/*
10962882Svi117747 	 * Get method.
10972882Svi117747 	 */
10982882Svi117747 	if (sip_skip_white_space(sip_header) != 0) {
10992882Svi117747 		cseq_value->sip_value_state = SIP_VALUE_BAD;
11002882Svi117747 		cseq_value->sip_value_end = sip_header->sip_hdr_end - 2;
11012882Svi117747 		goto cseq_parse_done;
11022882Svi117747 	}
11032882Svi117747 
11042882Svi117747 	tmp_ptr = sip_header->sip_hdr_current;
11052882Svi117747 
11062882Svi117747 	if (sip_find_white_space(sip_header)) {
11072882Svi117747 		cseq_value->sip_value_state = SIP_VALUE_BAD;
11082882Svi117747 		cseq_value->sip_value_end = sip_header->sip_hdr_current;
11092882Svi117747 		goto cseq_parse_done;
11102882Svi117747 	}
11112882Svi117747 
11122882Svi117747 	len = sip_header->sip_hdr_current - tmp_ptr;
11132882Svi117747 
11142882Svi117747 	for (i = 1; i < MAX_SIP_METHODS; i++) {
11152882Svi117747 		if (strncmp(sip_methods[i].name, tmp_ptr, len) == 0)
11162882Svi117747 			break;
11172882Svi117747 	}
11182882Svi117747 
11192882Svi117747 	if (i >= MAX_SIP_METHODS) {
11202882Svi117747 		cseq_value->sip_value_state = SIP_VALUE_BAD;
11212882Svi117747 		cseq_value->sip_value_end = sip_header->sip_hdr_current;
11222882Svi117747 		goto cseq_parse_done;
11232882Svi117747 	}
11242882Svi117747 
11252882Svi117747 	cseq_value->cseq_method = i;
11262882Svi117747 	cseq_value->sip_value_end = sip_header->sip_hdr_current;
11272882Svi117747 cseq_parse_done:
11282882Svi117747 
11292882Svi117747 	sip_header->sip_hdr_parsed = parsed_header;
11302882Svi117747 
11312882Svi117747 	*header = parsed_header;
11322882Svi117747 	return (0);
11332882Svi117747 }
11342882Svi117747 
11352882Svi117747 
11362882Svi117747 /*
11372882Svi117747  * Via =  ( "Via" / "v" ) HCOLON via-parm *(COMMA via-parm)
11382882Svi117747  * via-parm          =  sent-protocol LWS sent-by *( SEMI via-params )
11392882Svi117747  * via-params        =  via-ttl / via-maddr
11402882Svi117747  *                      / via-received / via-branch
11412882Svi117747  *                      / via-extension
11422882Svi117747  * via-ttl           =  "ttl" EQUAL ttl
11432882Svi117747  * via-maddr         =  "maddr" EQUAL host
11442882Svi117747  * via-received      =  "received" EQUAL (IPv4address / IPv6address)
11452882Svi117747  * via-branch        =  "branch" EQUAL token
11462882Svi117747  * via-extension     =  generic-param
11472882Svi117747  * sent-protocol     =  protocol-name SLASH protocol-version
11482882Svi117747  *                      SLASH transport
11492882Svi117747  * protocol-name     =  "SIP" / token
11502882Svi117747  * protocol-version  =  token
11512882Svi117747  * transport         =  "UDP" / "TCP" / "TLS" / "SCTP"
11522882Svi117747  *                      / other-transport
11532882Svi117747  * sent-by           =  host [ COLON port ]
11542882Svi117747  * ttl               =  1*3DIGIT ; 0 to 255
11552882Svi117747  *
11562882Svi117747  * There can be multiple via headers we always append the header.
11572882Svi117747  */
11582882Svi117747 int
sip_parse_via_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)11592882Svi117747 sip_parse_via_header(_sip_header_t *sip_header, sip_parsed_header_t **header)
11602882Svi117747 {
11612882Svi117747 	sip_parsed_header_t	*parsed_header;
11622882Svi117747 	int			ret;
11632882Svi117747 	sip_hdr_value_t		*value = NULL;
11642882Svi117747 	sip_hdr_value_t		*last_value = NULL;
11652882Svi117747 
11662882Svi117747 	if ((ret = sip_prim_parsers(sip_header, header)) != 0)
11672882Svi117747 		return (ret);
11682882Svi117747 
11692882Svi117747 	if (*header != NULL)
11702882Svi117747 		return (0);
11712882Svi117747 
11722882Svi117747 	parsed_header = calloc(1, sizeof (sip_parsed_header_t));
11732882Svi117747 	if (parsed_header == NULL)
11742882Svi117747 		return (ENOMEM);
11752882Svi117747 	parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1;
11762882Svi117747 	parsed_header->sip_header = sip_header;
11772882Svi117747 
11782882Svi117747 	while (sip_header->sip_hdr_current < sip_header->sip_hdr_end) {
11792882Svi117747 
11802882Svi117747 		value = calloc(1, sizeof (sip_hdr_value_t));
11812882Svi117747 		if (value == NULL) {
11822882Svi117747 			sip_free_phdr(parsed_header);
11832882Svi117747 			return (ENOMEM);
11842882Svi117747 		}
11852882Svi117747 		if (last_value != NULL)
11862882Svi117747 			last_value->sip_next_value = value;
11872882Svi117747 		else
11882882Svi117747 			parsed_header->value = (sip_value_t *)value;
11892882Svi117747 
11902882Svi117747 		value->sip_value_version = SIP_VALUE_VERSION_1;
11912882Svi117747 		value->sip_value_start = sip_header->sip_hdr_current;
11922882Svi117747 		value->sip_value_header = parsed_header;
11932882Svi117747 		value->via_protocol_name.sip_str_ptr =
11942882Svi117747 		    sip_header->sip_hdr_current;
11952882Svi117747 
11962882Svi117747 		/*
11972882Svi117747 		 * Check to see if there is a version number
11982882Svi117747 		 */
11992882Svi117747 		if (sip_get_protocol_version(sip_header,
12002882Svi117747 		    &value->via_protocol) != 0) {
12012882Svi117747 			if (sip_goto_next_value(sip_header) != 0) {
12022882Svi117747 				sip_free_phdr(parsed_header);
12032882Svi117747 				return (EPROTO);
12042882Svi117747 			}
12052882Svi117747 			value->sip_value_state = SIP_VALUE_BAD;
12062882Svi117747 			goto get_next_via_value;
12072882Svi117747 		}
12082882Svi117747 
12092882Svi117747 		if (sip_find_token(sip_header, SIP_SLASH) != 0) {
12102882Svi117747 			if (sip_goto_next_value(sip_header) != 0) {
12112882Svi117747 				sip_free_phdr(parsed_header);
12122882Svi117747 				return (EPROTO);
12132882Svi117747 			}
12142882Svi117747 			value->sip_value_state = SIP_VALUE_BAD;
12152882Svi117747 			goto get_next_via_value;
12162882Svi117747 		}
12172882Svi117747 
12182882Svi117747 		if (sip_skip_white_space(sip_header) != 0) {
12192882Svi117747 			if (sip_goto_next_value(sip_header) != 0) {
12202882Svi117747 				sip_free_phdr(parsed_header);
12212882Svi117747 				return (EPROTO);
12222882Svi117747 			}
12232882Svi117747 			value->sip_value_state = SIP_VALUE_BAD;
12242882Svi117747 			goto get_next_via_value;
12252882Svi117747 		}
12262882Svi117747 
12272882Svi117747 		value->via_protocol_transport.sip_str_ptr =
12282882Svi117747 		    sip_header->sip_hdr_current;
12292882Svi117747 		if (sip_find_white_space(sip_header) != 0) {
12302882Svi117747 			if (sip_goto_next_value(sip_header) != 0) {
12312882Svi117747 				sip_free_phdr(parsed_header);
12322882Svi117747 				return (EPROTO);
12332882Svi117747 			}
12342882Svi117747 			value->sip_value_state = SIP_VALUE_BAD;
12352882Svi117747 			goto get_next_via_value;
12362882Svi117747 		}
12372882Svi117747 
12382882Svi117747 		value->via_protocol_transport.sip_str_len =
12392882Svi117747 		    sip_header->sip_hdr_current -
12402882Svi117747 		    value->via_protocol_transport.sip_str_ptr;
12412882Svi117747 
12422882Svi117747 		if (sip_skip_white_space(sip_header) != 0) {
12432882Svi117747 			if (sip_goto_next_value(sip_header) != 0) {
12442882Svi117747 				sip_free_phdr(parsed_header);
12452882Svi117747 				return (EPROTO);
12462882Svi117747 			}
12472882Svi117747 			value->sip_value_state = SIP_VALUE_BAD;
12482882Svi117747 			goto get_next_via_value;
12492882Svi117747 		}
12502882Svi117747 
12512882Svi117747 		value->via_sent_by_host.sip_str_ptr =
12522882Svi117747 		    sip_header->sip_hdr_current;
12532882Svi117747 		if (*sip_header->sip_hdr_current == '[') {
12542882Svi117747 			if (sip_find_token(sip_header, ']')) {
12552882Svi117747 				if (sip_goto_next_value(sip_header) != 0) {
12562882Svi117747 					sip_free_phdr(parsed_header);
12572882Svi117747 					return (EPROTO);
12582882Svi117747 				}
12592882Svi117747 				value->sip_value_state = SIP_VALUE_BAD;
12602882Svi117747 				goto get_next_via_value;
12612882Svi117747 			}
12622882Svi117747 		} else if (sip_find_separator(sip_header, SIP_SEMI, SIP_COMMA,
1263*5092Sgm209912 		    SIP_HCOLON, B_FALSE)) {
12642882Svi117747 			if (sip_goto_next_value(sip_header) != 0) {
12652882Svi117747 				sip_free_phdr(parsed_header);
12662882Svi117747 				return (EPROTO);
12672882Svi117747 			}
12682882Svi117747 			value->sip_value_state = SIP_VALUE_BAD;
12692882Svi117747 			goto get_next_via_value;
12702882Svi117747 		}
12712882Svi117747 		value->via_sent_by_host.sip_str_len =
12722882Svi117747 		    sip_header->sip_hdr_current -
12732882Svi117747 		    value->via_sent_by_host.sip_str_ptr;
12742882Svi117747 
12752882Svi117747 		if (sip_skip_white_space(sip_header) != 0) {
12762882Svi117747 			if (sip_goto_next_value(sip_header) != 0) {
12772882Svi117747 				sip_free_phdr(parsed_header);
12782882Svi117747 				return (EPROTO);
12792882Svi117747 			}
12802882Svi117747 			value->sip_value_state = SIP_VALUE_BAD;
12812882Svi117747 			goto get_next_via_value;
12822882Svi117747 		}
12832882Svi117747 
12842882Svi117747 		if (*sip_header->sip_hdr_current == SIP_HCOLON) {
12852882Svi117747 			sip_header->sip_hdr_current++;
12862882Svi117747 			/*
12872882Svi117747 			 * We have a port number
12882882Svi117747 			 */
12892882Svi117747 			if (sip_atoi(sip_header, &value->via_sent_by_port) !=
12902882Svi117747 			    0) {
12912882Svi117747 				if (sip_goto_next_value(sip_header) != 0) {
12922882Svi117747 					sip_free_phdr(parsed_header);
12932882Svi117747 					return (EPROTO);
12942882Svi117747 				}
12952882Svi117747 				value->sip_value_state = SIP_VALUE_BAD;
12962882Svi117747 				goto get_next_via_value;
12972882Svi117747 			}
12982882Svi117747 
12992882Svi117747 		}
13002882Svi117747 
13012882Svi117747 		/*
13022882Svi117747 		 * Do some sanity checking.
13032882Svi117747 		 * This should be replaced by a v4/v6 address check.
13042882Svi117747 		 */
13052882Svi117747 		if (value->via_sent_by_host.sip_str_len == 0 ||
13062882Svi117747 		    (!isalnum(*value->via_sent_by_host.sip_str_ptr) &&
13072882Svi117747 		    *value->via_sent_by_host.sip_str_ptr != '[')) {
13082882Svi117747 			if (sip_goto_next_value(sip_header) != 0) {
13092882Svi117747 				sip_free_phdr(parsed_header);
13102882Svi117747 				return (EPROTO);
13112882Svi117747 			}
13122882Svi117747 			value->sip_value_state = SIP_VALUE_BAD;
13132882Svi117747 			goto get_next_via_value;
13142882Svi117747 		}
13152882Svi117747 
13162882Svi117747 		ret = sip_parse_params(sip_header, &value->sip_param_list);
13172882Svi117747 		if (ret == EPROTO) {
13182882Svi117747 			value->sip_value_state = SIP_VALUE_BAD;
13192882Svi117747 		} else if (ret != 0) {
13202882Svi117747 			sip_free_phdr(parsed_header);
13212882Svi117747 			return (ret);
13222882Svi117747 		}
13232882Svi117747 get_next_via_value:
13242882Svi117747 		value->sip_value_end = sip_header->sip_hdr_current;
13252882Svi117747 
13262882Svi117747 		if (sip_find_token(sip_header, SIP_COMMA) != 0)
13272882Svi117747 			break;
13282882Svi117747 		last_value = value;
13292882Svi117747 		(void) sip_skip_white_space(sip_header);
13302882Svi117747 	}
13312882Svi117747 
13322882Svi117747 	sip_header->sip_hdr_parsed = parsed_header;
13332882Svi117747 
13342882Svi117747 	*header = parsed_header;
13352882Svi117747 	return (0);
13362882Svi117747 }
13372882Svi117747 
13382882Svi117747 /*
13392882Svi117747  * Max-Forwards  =  "Max-Forwards" HCOLON 1*DIGIT
13402882Svi117747  */
13412882Svi117747 int
sip_parse_maxf_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)13422882Svi117747 sip_parse_maxf_header(_sip_header_t *sip_header, sip_parsed_header_t **header)
13432882Svi117747 {
13442882Svi117747 	return (sip_parse_hdr_parser2(sip_header, header, SIP_INT_VAL));
13452882Svi117747 }
13462882Svi117747 
13472882Svi117747 /*
13482882Svi117747  * Content-Type     =  ( "Content-Type" / "c" ) HCOLON media-type
13492882Svi117747  * media-type       =  m-type SLASH m-subtype *(SEMI m-parameter)
13502882Svi117747  * m-type           =  discrete-type / composite-type
13512882Svi117747  * discrete-type    =  "text" / "image" / "audio" / "video"
13522882Svi117747  *                     / "application" / extension-token
13532882Svi117747  * composite-type   =  "message" / "multipart" / extension-token
13542882Svi117747  * extension-token  =  ietf-token / x-token
13552882Svi117747  * ietf-token       =  token
13562882Svi117747  * x-token          =  "x-" token
13572882Svi117747  * m-subtype        =  extension-token / iana-token
13582882Svi117747  * iana-token       =  token
13592882Svi117747  * m-parameter      =  m-attribute EQUAL m-value
13602882Svi117747  * m-attribute      =  token
13612882Svi117747  * m-value          =  token / quoted-string
13622882Svi117747  */
13632882Svi117747 int
sip_parse_ctype_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)13642882Svi117747 sip_parse_ctype_header(_sip_header_t *sip_header, sip_parsed_header_t **header)
13652882Svi117747 {
13662882Svi117747 	return (sip_parse_hdr_parser1(sip_header, header, SIP_SLASH));
13672882Svi117747 }
13682882Svi117747 
13692882Svi117747 /*
13702882Svi117747  * Content-Length  =  ( "Content-Length" / "l" ) HCOLON 1*DIGIT
13712882Svi117747  */
13722882Svi117747 int
sip_parse_clen_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)13732882Svi117747 sip_parse_clen_header(_sip_header_t *sip_header, sip_parsed_header_t **header)
13742882Svi117747 {
13752882Svi117747 	return (sip_parse_hdr_parser2(sip_header, header, SIP_INT_VAL));
13762882Svi117747 }
13772882Svi117747 
13782882Svi117747 /*
13792882Svi117747  * Generic parser for Contact, From, To, Route and Record-Route headers
13802882Svi117747  *
13812882Svi117747  * Contact = ("Contact" / "m" ) HCOLON
13822882Svi117747  *		( STAR / (contact-param *(COMMA contact-param)))
13832882Svi117747  * contact-param  =  (name-addr / addr-spec) *(SEMI contact-params)
13842882Svi117747  * name-addr      =  [ display-name ] LAQUOT addr-spec RAQUOT
13852882Svi117747  * addr-spec      =  SIP-URI / SIPS-URI / absoluteURI
13862882Svi117747  * display-name   =  *(token LWS)/ quoted-string
13872882Svi117747  * contact-params     =  c-p-q / c-p-expires
13882882Svi117747  *                     / contact-extension
13892882Svi117747  *
13902882Svi117747  * From =  ( "From" / "f" ) HCOLON from-spec
13912882Svi117747  * from-spec = ( name-addr / addr-spec )
13922882Svi117747  *	*( SEMI from-param )
13932882Svi117747  * from-param  =  tag-param / generic-param
13942882Svi117747  * tag-param   =  "tag" EQUAL token
13952882Svi117747  *
13962882Svi117747  * To =  ( "To" / "t" ) HCOLON ( name-addr
13972882Svi117747  *	/ addr-spec ) *( SEMI to-param )
13982882Svi117747  * to-param  =  tag-param / generic-param
13992882Svi117747  *
14002882Svi117747  * Route        =  "Route" HCOLON route-param *(COMMA route-param)
14012882Svi117747  * route-param  =  name-addr *( SEMI rr-param )
14022882Svi117747  *
14032882Svi117747  * Record-Route  =  "Record-Route" HCOLON rec-route *(COMMA rec-route)
14042882Svi117747  * rec-route     =  name-addr *( SEMI rr-param )
14052882Svi117747  * rr-param      =  generic-param
14062882Svi117747  *
14072882Svi117747  * We could have multiple values for these headers. For the ones that have
14082882Svi117747  * a display name we will have a LAQUOT/RAQUOT. If we encounter an error
14092882Svi117747  * when parsing a value, we mark the value as bad and start paring the
14102882Svi117747  * next value, if present. Before we start parsing the next value, we
14112882Svi117747  * check for any parameters, if present.
14122882Svi117747  */
14132882Svi117747 int
sip_parse_cftr_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)14142882Svi117747 sip_parse_cftr_header(_sip_header_t *sip_header, sip_parsed_header_t **header)
14152882Svi117747 {
14162882Svi117747 	sip_parsed_header_t	*parsed_header;
14172882Svi117747 	char			*tmp_ptr;
14182882Svi117747 	char			*tmp_ptr_2;
14192882Svi117747 	int			ret;
14202882Svi117747 	sip_hdr_value_t		*value = NULL;
14212882Svi117747 	sip_hdr_value_t		*last_value = NULL;
14222882Svi117747 
14232882Svi117747 	if ((ret = sip_prim_parsers(sip_header, header)) != 0)
14242882Svi117747 		return (ret);
14252882Svi117747 
14262882Svi117747 	if (*header != NULL)
14272882Svi117747 		return (0);
14282882Svi117747 
14292882Svi117747 	parsed_header = calloc(1, sizeof (sip_parsed_header_t));
14302882Svi117747 	if (parsed_header == NULL)
14312882Svi117747 		return (ENOMEM);
14322882Svi117747 	parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1;
14332882Svi117747 	parsed_header->sip_header = sip_header;
14342882Svi117747 	while (sip_header->sip_hdr_current < sip_header->sip_hdr_end) {
14352882Svi117747 		boolean_t	quoted_name = B_FALSE;
14362882Svi117747 
14372882Svi117747 		value =  calloc(1, sizeof (sip_hdr_value_t));
14382882Svi117747 		if (value == NULL) {
14392882Svi117747 			sip_free_cftr_header(parsed_header);
14402882Svi117747 			return (ENOMEM);
14412882Svi117747 		}
14422882Svi117747 		if (last_value != NULL)
14432882Svi117747 			last_value->sip_next_value = value;
14442882Svi117747 		else
14452882Svi117747 			parsed_header->value = (sip_value_t *)value;
14462882Svi117747 		if (*sip_header->sip_hdr_current == SIP_QUOTE) {
14472882Svi117747 			sip_header->sip_hdr_current++;
14482882Svi117747 			quoted_name = B_TRUE;
14492882Svi117747 		}
14502882Svi117747 		value->sip_value_version = SIP_VALUE_VERSION_1;
14512882Svi117747 		value->sip_value_start = sip_header->sip_hdr_current;
14522882Svi117747 		value->sip_value_header = parsed_header;
14532882Svi117747 		/*
14542882Svi117747 		 * let's see if there is a display name
14552882Svi117747 		 */
14562882Svi117747 		if (*sip_header->sip_hdr_current != SIP_LAQUOT) {
14572882Svi117747 
14582882Svi117747 			tmp_ptr = sip_header->sip_hdr_current;
14592882Svi117747 			/*
14602882Svi117747 			 * According to 20.10 '<' may not have a leading
14612882Svi117747 			 * space.
14622882Svi117747 			 */
14632882Svi117747 			if (quoted_name &&
14642882Svi117747 			    sip_find_token(sip_header, SIP_QUOTE) != 0) {
14652882Svi117747 				if (sip_goto_next_value(sip_header) != 0) {
14662882Svi117747 					sip_free_cftr_header(parsed_header);
14672882Svi117747 					return (EPROTO);
14682882Svi117747 				}
14692882Svi117747 				value->sip_value_state = SIP_VALUE_BAD;
14702882Svi117747 				goto get_next_cftr_value;
14712882Svi117747 			} else if (sip_find_separator(sip_header, SIP_SEMI,
1472*5092Sgm209912 			    SIP_LAQUOT, SIP_COMMA, B_TRUE) != 0) {
14732882Svi117747 				/*
14742882Svi117747 				 * only a uri.
14752882Svi117747 				 */
14762882Svi117747 				value->cftr_uri.sip_str_ptr = tmp_ptr;
14772882Svi117747 				value->cftr_uri.sip_str_len =
14782882Svi117747 				    sip_header->sip_hdr_current - tmp_ptr;
14792882Svi117747 				/*
14802882Svi117747 				 * It's an error not to have a uri.
14812882Svi117747 				 */
14822882Svi117747 				if (value->cftr_uri.sip_str_len == 0) {
14832882Svi117747 					if (sip_goto_next_value(sip_header) !=
14842882Svi117747 					    0) {
14852882Svi117747 						sip_free_cftr_header(
14862882Svi117747 						    parsed_header);
14872882Svi117747 						return (EPROTO);
14882882Svi117747 					}
14892882Svi117747 					value->sip_value_state = SIP_VALUE_BAD;
14902882Svi117747 					goto get_next_cftr_value;
14912882Svi117747 				}
1492*5092Sgm209912 				goto get_next_cftr_value;
14932882Svi117747 			}
1494*5092Sgm209912 			/*
1495*5092Sgm209912 			 * This is needed to get rid of leading white spaces of
1496*5092Sgm209912 			 * display name or uri
1497*5092Sgm209912 			 */
1498*5092Sgm209912 			--sip_header->sip_hdr_current;
1499*5092Sgm209912 			(void) sip_reverse_skip_white_space(sip_header);
1500*5092Sgm209912 			++sip_header->sip_hdr_current;
15012882Svi117747 			tmp_ptr_2 = sip_header->sip_hdr_current;
15022882Svi117747 			if (*sip_header->sip_hdr_current == SIP_SP) {
15032882Svi117747 				if (sip_skip_white_space(sip_header) != 0) {
15042882Svi117747 					/*
15052882Svi117747 					 * only a uri.
15062882Svi117747 					 */
15072882Svi117747 					value->cftr_uri.sip_str_ptr = tmp_ptr;
15082882Svi117747 					value->cftr_uri.sip_str_len =
15092882Svi117747 					    tmp_ptr_2 - tmp_ptr;
15102882Svi117747 					/*
15112882Svi117747 					 * It's an error not to have a uri.
15122882Svi117747 					 */
15132882Svi117747 					if (value->cftr_uri.sip_str_len == 0) {
15142882Svi117747 						if (sip_goto_next_value(
15152882Svi117747 						    sip_header) != 0) {
15162882Svi117747 							sip_free_cftr_header(
15172882Svi117747 							    parsed_header);
15182882Svi117747 							return (EPROTO);
15192882Svi117747 						}
15202882Svi117747 						value->sip_value_state =
15212882Svi117747 						    SIP_VALUE_BAD;
15222882Svi117747 						goto get_next_cftr_value;
15232882Svi117747 					}
1524*5092Sgm209912 					goto get_next_cftr_value;
15252882Svi117747 				}
15262882Svi117747 			}
15272882Svi117747 
15282882Svi117747 			if (*sip_header->sip_hdr_current != SIP_LAQUOT) {
15292882Svi117747 				/*
15302882Svi117747 				 * No display name here.
15312882Svi117747 				 */
15322882Svi117747 				value->cftr_uri.sip_str_ptr = tmp_ptr;
15332882Svi117747 				value->cftr_uri.sip_str_len = tmp_ptr_2 -
15342882Svi117747 				    tmp_ptr;
15352882Svi117747 				/*
15362882Svi117747 				 * It's an error not to have a uri.
15372882Svi117747 				 */
15382882Svi117747 				if (value->cftr_uri.sip_str_len == 0) {
15392882Svi117747 					if (sip_goto_next_value(sip_header) !=
15402882Svi117747 					    0) {
15412882Svi117747 						sip_free_cftr_header(
15422882Svi117747 						    parsed_header);
15432882Svi117747 						return (EPROTO);
15442882Svi117747 					}
15452882Svi117747 					value->sip_value_state = SIP_VALUE_BAD;
15462882Svi117747 					goto get_next_cftr_value;
15472882Svi117747 				}
15482882Svi117747 				goto get_params;
15492882Svi117747 			}
15502882Svi117747 
15512882Svi117747 			value->cftr_name = malloc(sizeof (sip_str_t));
15522882Svi117747 			if (value->cftr_name == NULL) {
15532882Svi117747 				sip_free_cftr_header(parsed_header);
15542882Svi117747 				return (ENOMEM);
15552882Svi117747 			}
15562882Svi117747 			value->cftr_name->sip_str_ptr = tmp_ptr;
15572882Svi117747 			value->cftr_name->sip_str_len = tmp_ptr_2 - tmp_ptr;
15582882Svi117747 			if (quoted_name)
15592882Svi117747 				value->cftr_name->sip_str_len--;
15602882Svi117747 		}
15612882Svi117747 
15622882Svi117747 		if (sip_find_token(sip_header, SIP_LAQUOT) != 0) {
15632882Svi117747 			if (sip_goto_next_value(sip_header) != 0) {
15642882Svi117747 				sip_free_cftr_header(parsed_header);
15652882Svi117747 				return (EPROTO);
15662882Svi117747 			}
15672882Svi117747 			value->sip_value_state = SIP_VALUE_BAD;
15682882Svi117747 			goto get_next_cftr_value;
15692882Svi117747 		}
15702882Svi117747 
15712882Svi117747 		if (*sip_header->sip_hdr_current == SIP_SP) {
15722882Svi117747 			if (sip_skip_white_space(sip_header) != 0) {
15732882Svi117747 				if (sip_goto_next_value(sip_header) != 0) {
15742882Svi117747 					sip_free_cftr_header(parsed_header);
15752882Svi117747 					return (EPROTO);
15762882Svi117747 				}
15772882Svi117747 				value->sip_value_state = SIP_VALUE_BAD;
15782882Svi117747 				goto get_next_cftr_value;
15792882Svi117747 			}
15802882Svi117747 		}
15812882Svi117747 
15822882Svi117747 		tmp_ptr = sip_header->sip_hdr_current;
15832882Svi117747 
15842882Svi117747 		if (sip_find_separator(sip_header, SIP_RAQUOT, (char)NULL,
1585*5092Sgm209912 		    (char)NULL, B_FALSE)) {
15862882Svi117747 			if (sip_goto_next_value(sip_header) != 0) {
15872882Svi117747 				sip_free_cftr_header(parsed_header);
15882882Svi117747 				return (EPROTO);
15892882Svi117747 			}
15902882Svi117747 			value->sip_value_state = SIP_VALUE_BAD;
15912882Svi117747 			goto get_next_cftr_value;
15922882Svi117747 		}
15932882Svi117747 
15942882Svi117747 		value->cftr_uri.sip_str_ptr = tmp_ptr;
15952882Svi117747 		value->cftr_uri.sip_str_len =
15962882Svi117747 		    sip_header->sip_hdr_current - tmp_ptr;
15972882Svi117747 
15982882Svi117747 		if (sip_find_token(sip_header, SIP_RAQUOT) != 0) {
15992882Svi117747 			if (sip_goto_next_value(sip_header) != 0) {
16002882Svi117747 				sip_free_cftr_header(parsed_header);
16012882Svi117747 				return (EINVAL);
16022882Svi117747 			}
16032882Svi117747 			value->sip_value_state = SIP_VALUE_BAD;
16042882Svi117747 			goto get_next_cftr_value;
16052882Svi117747 		}
16062882Svi117747 
16072882Svi117747 		if (value->cftr_uri.sip_str_len <= strlen("<>")) {
16082882Svi117747 			if (sip_goto_next_value(sip_header) != 0) {
16092882Svi117747 				sip_free_cftr_header(parsed_header);
16102882Svi117747 				return (EPROTO);
16112882Svi117747 			}
16122882Svi117747 			value->sip_value_state = SIP_VALUE_BAD;
16132882Svi117747 			goto get_next_cftr_value;
16142882Svi117747 		}
16152882Svi117747 
16162882Svi117747 get_params:
16172882Svi117747 		ret = sip_parse_params(sip_header, &value->sip_param_list);
16182882Svi117747 		if (ret == EPROTO) {
16192882Svi117747 			value->sip_value_state = SIP_VALUE_BAD;
16202882Svi117747 		} else if (ret != 0) {
16212882Svi117747 			sip_free_cftr_header(parsed_header);
16222882Svi117747 			return (ret);
16232882Svi117747 		}
16242882Svi117747 get_next_cftr_value:
16252882Svi117747 		value->sip_value_end = sip_header->sip_hdr_current;
16262882Svi117747 
16272882Svi117747 		/*
16282882Svi117747 		 * Parse uri
16292882Svi117747 		 */
16302882Svi117747 		if (value->cftr_uri.sip_str_len > 0) {
1631*5092Sgm209912 			int			error;
1632*5092Sgm209912 			uint_t			uri_errflags;
1633*5092Sgm209912 			char			*uri = "*";
1634*5092Sgm209912 			_sip_msg_t		*sip_msg;
1635*5092Sgm209912 			sip_message_type_t	*msg_type;
16362882Svi117747 
16372882Svi117747 			value->sip_value_parsed_uri = sip_parse_uri(
16382882Svi117747 			    &value->cftr_uri, &error);
16392882Svi117747 			if (value->sip_value_parsed_uri == NULL) {
16402882Svi117747 				sip_free_cftr_header(parsed_header);
16412882Svi117747 				return (ENOMEM);
16422882Svi117747 			}
1643*5092Sgm209912 			uri_errflags = ((_sip_uri_t *)value->
1644*5092Sgm209912 			    sip_value_parsed_uri)->sip_uri_errflags;
1645*5092Sgm209912 			if (error != 0 || uri_errflags != 0) {
1646*5092Sgm209912 				if ((strcmp(SIP_CONTACT, sip_header->
1647*5092Sgm209912 				    sip_header_functions->header_name) == 0) &&
1648*5092Sgm209912 				    (strncmp(value->cftr_uri.sip_str_ptr, uri,
1649*5092Sgm209912 				    strlen(uri)) == 0) && (strlen(uri) ==
1650*5092Sgm209912 				    value->cftr_uri.sip_str_len)) {
1651*5092Sgm209912 					sip_msg = sip_header->sip_hdr_sipmsg;
1652*5092Sgm209912 					msg_type = sip_msg->sip_msg_req_res;
1653*5092Sgm209912 					if (msg_type->is_request && msg_type->
1654*5092Sgm209912 					    sip_req_method == REGISTER) {
1655*5092Sgm209912 						error = 0;
1656*5092Sgm209912 						((_sip_uri_t *)value->
1657*5092Sgm209912 						    sip_value_parsed_uri)->
1658*5092Sgm209912 						    sip_uri_errflags = 0;
1659*5092Sgm209912 					} else {
1660*5092Sgm209912 						value->sip_value_state =
1661*5092Sgm209912 						    SIP_VALUE_BAD;
1662*5092Sgm209912 					}
1663*5092Sgm209912 				} else {
1664*5092Sgm209912 					value->sip_value_state = SIP_VALUE_BAD;
1665*5092Sgm209912 				}
16662882Svi117747 			}
16672882Svi117747 		}
16682882Svi117747 
16692882Svi117747 		(void) sip_find_token(sip_header, SIP_COMMA);
16702882Svi117747 		last_value = value;
16712882Svi117747 		(void) sip_skip_white_space(sip_header);
16722882Svi117747 	}
16732882Svi117747 
16742882Svi117747 	sip_header->sip_hdr_parsed = parsed_header;
16752882Svi117747 
16762882Svi117747 	*header = parsed_header;
16772882Svi117747 	return (0);
16782882Svi117747 }
16792882Svi117747 
16802882Svi117747 /*
16812882Svi117747  * PAssertedID = "P-Asserted-Identity" HCOLON PAssertedID-value
16822882Svi117747  *               *(COMMA PAssertedID-value)
16832882Svi117747  * PAssertedID-value = name-addr / addr-spec
16842882Svi117747  */
16852882Svi117747 int
sip_parse_passertedid(_sip_header_t * sip_header,sip_parsed_header_t ** header)16862882Svi117747 sip_parse_passertedid(_sip_header_t *sip_header, sip_parsed_header_t **header)
16872882Svi117747 {
16882882Svi117747 	return (sip_parse_hdr_parser3(sip_header, header, SIP_STRS_VAL,
16892882Svi117747 	    B_TRUE));
16902882Svi117747 }
16912882Svi117747 
16922882Svi117747 /*
16932882Svi117747  * PPreferredID = "P-Preferred-Identity" HCOLON PPreferredID-value
16942882Svi117747  *               *(COMMA PAssertedID-value)
16952882Svi117747  * PPreferredID-value = name-addr / addr-spec
16962882Svi117747  */
16972882Svi117747 int
sip_parse_ppreferredid(_sip_header_t * sip_header,sip_parsed_header_t ** header)16982882Svi117747 sip_parse_ppreferredid(_sip_header_t *sip_header, sip_parsed_header_t **header)
16992882Svi117747 {
17002882Svi117747 	return (sip_parse_hdr_parser3(sip_header, header, SIP_STRS_VAL,
17012882Svi117747 	    B_TRUE));
17022882Svi117747 }
17032882Svi117747 
17042882Svi117747 
17052882Svi117747 /*
17062882Svi117747  * We don't do anything for a header we don't understand
17072882Svi117747  */
17082882Svi117747 /* ARGSUSED */
17092882Svi117747 int
sip_parse_unknown_header(_sip_header_t * sip_header,sip_parsed_header_t ** header)17102882Svi117747 sip_parse_unknown_header(_sip_header_t *sip_header,
17112882Svi117747     sip_parsed_header_t **header)
17122882Svi117747 {
17132882Svi117747 	return (EINVAL);
17142882Svi117747 }
1715