xref: /onnv-gate/usr/src/lib/libsip/common/sip_add_hdrs.c (revision 3439:0302bfe973fe)
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 /*
23*3439Svi117747  * 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 
29*3439Svi117747 #include <stdio.h>
30*3439Svi117747 #include <ctype.h>
31*3439Svi117747 #include <errno.h>
32*3439Svi117747 #include <pthread.h>
33*3439Svi117747 #include <strings.h>
34*3439Svi117747 #include <stdlib.h>
35*3439Svi117747 #include <sip.h>
36*3439Svi117747 
372882Svi117747 #include "sip_msg.h"
382882Svi117747 #include "sip_miscdefs.h"
392882Svi117747 
402882Svi117747 /*
412882Svi117747  * Returns number of digits in the given int
422882Svi117747  */
432882Svi117747 static int
sip_num_of_digits(int num)442882Svi117747 sip_num_of_digits(int num)
452882Svi117747 {
462882Svi117747 	int	num_of_bytes = 0;
472882Svi117747 
482882Svi117747 	do {
492882Svi117747 		num_of_bytes += 1;
502882Svi117747 		num = num / 10;
512882Svi117747 	} while (num > 0);
522882Svi117747 	return (num_of_bytes);
532882Svi117747 }
542882Svi117747 
552882Svi117747 /*
562882Svi117747  * Return the int as a string
572882Svi117747  */
582882Svi117747 static char *
sip_int_to_str(int i)592882Svi117747 sip_int_to_str(int i)
602882Svi117747 {
612882Svi117747 	int	count;
622882Svi117747 	int	t;
632882Svi117747 	int	x;
642882Svi117747 	char	*str;
652882Svi117747 
662882Svi117747 	if (i < 0)
672882Svi117747 		return (NULL);
682882Svi117747 	/*
692882Svi117747 	 * the following two loops convert int i to str
702882Svi117747 	 */
712882Svi117747 	count = 1;
722882Svi117747 	t = i;
732882Svi117747 	while ((t = t / 10) != 0) {
742882Svi117747 		count++;
752882Svi117747 	}
762882Svi117747 
772882Svi117747 	str = calloc(1, sizeof (char) * count + 1);
782882Svi117747 	if (str == NULL)
792882Svi117747 		return (NULL);
802882Svi117747 	t = i;
812882Svi117747 	for (x = 0; x < count; x++) {
822882Svi117747 		int a;
832882Svi117747 		a = t % 10;
842882Svi117747 		str[count - 1 - x] = a + '0';
852882Svi117747 		t = t / 10;
862882Svi117747 	}
872882Svi117747 	str[count] = '\0';
882882Svi117747 	return (str);
892882Svi117747 }
902882Svi117747 
912882Svi117747 /*
922882Svi117747  * Add quotes to the give str and return the quoted string
932882Svi117747  */
942882Svi117747 static char *
sip_add_aquot_to_str(char * str,boolean_t * alloc)952882Svi117747 sip_add_aquot_to_str(char *str, boolean_t *alloc)
962882Svi117747 {
972882Svi117747 	char 		*new_str;
982882Svi117747 	char 		*tmp = str;
992882Svi117747 	int		size;
1002882Svi117747 
1012882Svi117747 	while (isspace(*tmp))
1022882Svi117747 		tmp++;
1032882Svi117747 
1042882Svi117747 	*alloc = B_FALSE;
1052882Svi117747 	if (*tmp != SIP_LAQUOT) {
1062882Svi117747 		size = strlen(str) + 2 * sizeof (char);
1072882Svi117747 		new_str = calloc(1, size + 1);
1082882Svi117747 		if (new_str == NULL)
1092882Svi117747 			return (NULL);
1102882Svi117747 		new_str[0] = SIP_LAQUOT;
1112882Svi117747 		new_str[1] = '\0';
1122882Svi117747 		(void) strncat(new_str, str, strlen(str));
1132882Svi117747 		(void) strncat(new_str, ">", 1);
1142882Svi117747 		new_str[size] = '\0';
1152882Svi117747 		*alloc = B_TRUE;
1162882Svi117747 		return (new_str);
1172882Svi117747 	}
1182882Svi117747 
1192882Svi117747 	return (str);
1202882Svi117747 }
1212882Svi117747 
1222882Svi117747 /*
1232882Svi117747  * Add an empty header
1242882Svi117747  */
1252882Svi117747 static int
sip_add_empty_hdr(sip_msg_t sip_msg,char * hdr_name)1262882Svi117747 sip_add_empty_hdr(sip_msg_t sip_msg, char *hdr_name)
1272882Svi117747 {
1282882Svi117747 	_sip_header_t	*new_header;
1292882Svi117747 	int 		header_size;
1302882Svi117747 	_sip_msg_t 	*_sip_msg;
1312882Svi117747 	int		csize = sizeof (char);
1322882Svi117747 
1332882Svi117747 	if (sip_msg == NULL || hdr_name == NULL)
1342882Svi117747 		return (EINVAL);
1352882Svi117747 	_sip_msg = (_sip_msg_t *)sip_msg;
1362882Svi117747 	(void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
1372882Svi117747 	if (_sip_msg->sip_msg_cannot_be_modified) {
1382882Svi117747 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
1392882Svi117747 		return (ENOTSUP);
1402882Svi117747 	}
1412882Svi117747 
1422882Svi117747 	header_size = strlen(hdr_name) + SIP_SPACE_LEN + csize;
1432882Svi117747 
1442882Svi117747 	new_header = sip_new_header(header_size);
1452882Svi117747 	if (new_header == NULL) {
1462882Svi117747 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
1472882Svi117747 		return (ENOMEM);
1482882Svi117747 	}
1492882Svi117747 
1502882Svi117747 	(void) snprintf(new_header->sip_hdr_start, header_size + 1,
1512882Svi117747 	    "%s %c",  hdr_name, SIP_HCOLON);
1522882Svi117747 
1532882Svi117747 	_sip_add_header(_sip_msg, new_header, B_TRUE, B_FALSE, hdr_name);
1542882Svi117747 	if (_sip_msg->sip_msg_buf != NULL)
1552882Svi117747 		_sip_msg->sip_msg_modified = B_TRUE;
1562882Svi117747 	(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
1572882Svi117747 
1582882Svi117747 	return (0);
1592882Svi117747 }
1602882Svi117747 
1612882Svi117747 /*
1622882Svi117747  * Generic function to add a header with two strings to message
1632882Svi117747  */
1642882Svi117747 static int
sip_add_2strs_to_msg(sip_msg_t sip_msg,char * hdr_name,char * str1,boolean_t qstr1,char * str2,char * plist,char sep)1652882Svi117747 sip_add_2strs_to_msg(sip_msg_t sip_msg, char *hdr_name, char *str1,
1662882Svi117747     boolean_t qstr1, char *str2, char *plist, char sep)
1672882Svi117747 {
1682882Svi117747 	_sip_header_t	*new_header;
1692882Svi117747 	int 		header_size;
1702882Svi117747 	_sip_msg_t 	*_sip_msg;
1712882Svi117747 	int		csize = sizeof (char);
1722882Svi117747 
1732882Svi117747 	if (sip_msg == NULL || str1 == NULL || str2 == NULL ||
1742882Svi117747 	    (str1 != NULL && str1[0] == '\0') ||
1752882Svi117747 	    (str2 != NULL && str2[0] == '\0')) {
1762882Svi117747 		return (EINVAL);
1772882Svi117747 	}
1782882Svi117747 	_sip_msg = (_sip_msg_t *)sip_msg;
1792882Svi117747 	(void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
1802882Svi117747 	if (_sip_msg->sip_msg_cannot_be_modified) {
1812882Svi117747 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
1822882Svi117747 		return (ENOTSUP);
1832882Svi117747 	}
1842882Svi117747 
1852882Svi117747 	if (plist == NULL) {
1862882Svi117747 		header_size = strlen(hdr_name) + SIP_SPACE_LEN + csize +
1872882Svi117747 		    SIP_SPACE_LEN + strlen(str1) + csize + strlen(str2) +
1882882Svi117747 		    strlen(SIP_CRLF);
1892882Svi117747 	} else {
1902882Svi117747 		header_size = strlen(hdr_name) + SIP_SPACE_LEN + csize +
1912882Svi117747 		    SIP_SPACE_LEN + strlen(str1) + csize + strlen(str2) +
1922882Svi117747 		    csize + strlen(plist) + strlen(SIP_CRLF);
1932882Svi117747 	}
1942882Svi117747 	if (qstr1)
1952882Svi117747 		header_size += 2 * sizeof (char);
1962882Svi117747 
1972882Svi117747 	new_header = sip_new_header(header_size);
1982882Svi117747 	if (new_header == NULL) {
1992882Svi117747 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
2002882Svi117747 		return (ENOMEM);
2012882Svi117747 	}
2022882Svi117747 
2032882Svi117747 	if (plist == NULL) {
2042882Svi117747 		if (qstr1) {
2052882Svi117747 			(void) snprintf(new_header->sip_hdr_start,
2062882Svi117747 			    header_size + 1, "%s %c \"%s\"%c%s%s",
2072882Svi117747 			    hdr_name, SIP_HCOLON, str1, sep, str2, SIP_CRLF);
2082882Svi117747 		} else {
2092882Svi117747 			(void) snprintf(new_header->sip_hdr_start,
2102882Svi117747 			    header_size + 1, "%s %c %s%c%s%s",
2112882Svi117747 			    hdr_name, SIP_HCOLON, str1, sep, str2, SIP_CRLF);
2122882Svi117747 		}
2132882Svi117747 	} else {
2142882Svi117747 		if (qstr1) {
2152882Svi117747 			(void) snprintf(new_header->sip_hdr_start,
2162882Svi117747 			    header_size + 1,
2172882Svi117747 			    "%s %c \"%s\"%c%s%c%s%s", hdr_name, SIP_HCOLON,
2182882Svi117747 			    str1, sep, str2, SIP_SEMI, plist, SIP_CRLF);
2192882Svi117747 		} else {
2202882Svi117747 			(void) snprintf(new_header->sip_hdr_start,
2212882Svi117747 			    header_size + 1, "%s %c %s%c%s%c%s%s",
2222882Svi117747 			    hdr_name, SIP_HCOLON, str1, sep, str2, SIP_SEMI,
2232882Svi117747 			    plist, SIP_CRLF);
2242882Svi117747 		}
2252882Svi117747 	}
2262882Svi117747 	_sip_add_header(_sip_msg, new_header, B_TRUE, B_FALSE, NULL);
2272882Svi117747 	if (_sip_msg->sip_msg_buf != NULL)
2282882Svi117747 		_sip_msg->sip_msg_modified = B_TRUE;
2292882Svi117747 	(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
2302882Svi117747 
2312882Svi117747 	return (0);
2322882Svi117747 }
2332882Svi117747 
2342882Svi117747 /*
2352882Svi117747  * Generic function to add a header with a string to message
2362882Svi117747  */
2372882Svi117747 static int
sip_add_str_to_msg(sip_msg_t sip_msg,char * hdr_name,char * str,char * plist,char param_sep)2382882Svi117747 sip_add_str_to_msg(sip_msg_t sip_msg, char *hdr_name, char *str, char *plist,
2392882Svi117747     char param_sep)
2402882Svi117747 {
2412882Svi117747 	_sip_header_t	*new_header;
2422882Svi117747 	int 		header_size;
2432882Svi117747 	_sip_msg_t 	*_sip_msg;
2442882Svi117747 	int		csize = sizeof (char);
2452882Svi117747 
2462882Svi117747 	if (sip_msg == NULL || str == NULL || (str != NULL && str[0] == '\0'))
2472882Svi117747 		return (EINVAL);
2482882Svi117747 	_sip_msg = (_sip_msg_t *)sip_msg;
2492882Svi117747 	(void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
2502882Svi117747 	if (_sip_msg->sip_msg_cannot_be_modified) {
2512882Svi117747 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
2522882Svi117747 		return (ENOTSUP);
2532882Svi117747 	}
2542882Svi117747 
2552882Svi117747 	if (plist == NULL) {
2562882Svi117747 		header_size = strlen(hdr_name) + SIP_SPACE_LEN + csize +
2572882Svi117747 		    SIP_SPACE_LEN + + strlen(str) + strlen(SIP_CRLF);
2582882Svi117747 	} else {
2592882Svi117747 		header_size = strlen(hdr_name) + SIP_SPACE_LEN + csize +
2602882Svi117747 		    SIP_SPACE_LEN + + strlen(str) + csize + strlen(plist) +
2612882Svi117747 		    strlen(SIP_CRLF);
2622882Svi117747 	}
2632882Svi117747 
2642882Svi117747 	new_header = sip_new_header(header_size);
2652882Svi117747 	if (new_header == NULL) {
2662882Svi117747 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
2672882Svi117747 		return (ENOMEM);
2682882Svi117747 	}
2692882Svi117747 	if (plist == NULL) {
2702882Svi117747 		(void) snprintf(new_header->sip_hdr_start, header_size + 1,
2712882Svi117747 		    "%s %c %s%s", hdr_name, SIP_HCOLON, str, SIP_CRLF);
2722882Svi117747 	} else {
2732882Svi117747 		(void) snprintf(new_header->sip_hdr_start, header_size + 1,
2742882Svi117747 		    "%s %c %s%c%s%s", hdr_name, SIP_HCOLON, str, param_sep,
2752882Svi117747 		    plist, SIP_CRLF);
2762882Svi117747 	}
2772882Svi117747 	_sip_add_header(_sip_msg, new_header, B_TRUE, B_FALSE, NULL);
2782882Svi117747 	if (_sip_msg->sip_msg_buf != NULL)
2792882Svi117747 		_sip_msg->sip_msg_modified = B_TRUE;
2802882Svi117747 	(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
2812882Svi117747 
2822882Svi117747 	return (0);
2832882Svi117747 }
2842882Svi117747 
2852882Svi117747 /*
2862882Svi117747  * Add an header with an int to sip_msg
2872882Svi117747  */
2882882Svi117747 static int
sip_add_int_to_msg(sip_msg_t sip_msg,char * hdr_name,int i,char * plist)2892882Svi117747 sip_add_int_to_msg(sip_msg_t sip_msg, char *hdr_name, int i, char *plist)
2902882Svi117747 {
2912882Svi117747 	_sip_header_t	*new_header;
2922882Svi117747 	int 		header_size;
2932882Svi117747 	_sip_msg_t 	*_sip_msg;
2942882Svi117747 	char		*digit_str;
2952882Svi117747 	int		csize = sizeof (char);
2962882Svi117747 
2972882Svi117747 	if (sip_msg == NULL || (hdr_name == NULL))
2982882Svi117747 		return (EINVAL);
2992882Svi117747 	_sip_msg = (_sip_msg_t *)sip_msg;
3002882Svi117747 	(void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
3012882Svi117747 	if (_sip_msg->sip_msg_cannot_be_modified) {
3022882Svi117747 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
3032882Svi117747 		return (ENOTSUP);
3042882Svi117747 	}
3052882Svi117747 
3062882Svi117747 	/*
3072882Svi117747 	 * the following two loops convert int i to str
3082882Svi117747 	 */
3092882Svi117747 	digit_str = sip_int_to_str(i);
3102882Svi117747 	if (digit_str == NULL)
3112882Svi117747 		return (EINVAL);
3122882Svi117747 
3132882Svi117747 	if (plist == NULL) {
3142882Svi117747 		header_size = strlen(hdr_name) + SIP_SPACE_LEN + csize +
3152882Svi117747 		    SIP_SPACE_LEN + strlen(digit_str) + strlen(SIP_CRLF);
3162882Svi117747 	} else {
3172882Svi117747 		header_size = strlen(hdr_name) + SIP_SPACE_LEN + csize +
3182882Svi117747 		    SIP_SPACE_LEN + strlen(digit_str) + csize +
3192882Svi117747 		    strlen(plist) + strlen(SIP_CRLF);
3202882Svi117747 	}
3212882Svi117747 
3222882Svi117747 	new_header = sip_new_header(header_size);
3232882Svi117747 	if (new_header == NULL) {
3242882Svi117747 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
3252882Svi117747 		free(digit_str);
3262882Svi117747 		return (ENOMEM);
3272882Svi117747 	}
3282882Svi117747 
3292882Svi117747 	if (plist == NULL) {
3302882Svi117747 		(void) snprintf(new_header->sip_hdr_start, header_size + 1,
3312882Svi117747 		    "%s %c %s%s", hdr_name, SIP_HCOLON, digit_str, SIP_CRLF);
3322882Svi117747 	} else {
3332882Svi117747 		(void) snprintf(new_header->sip_hdr_start, header_size + 1,
3342882Svi117747 		    "%s %c %s%c%s%s", hdr_name, SIP_HCOLON, digit_str,
3352882Svi117747 		    SIP_SEMI, plist, SIP_CRLF);
3362882Svi117747 	}
3372882Svi117747 	free(digit_str);
3382882Svi117747 	_sip_add_header(_sip_msg, new_header, B_TRUE, B_FALSE, NULL);
3392882Svi117747 	if (_sip_msg->sip_msg_buf != NULL)
3402882Svi117747 		_sip_msg->sip_msg_modified = B_TRUE;
3412882Svi117747 	(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
3422882Svi117747 
3432882Svi117747 	return (0);
3442882Svi117747 }
3452882Svi117747 
3462882Svi117747 /*
3472882Svi117747  * Add a header with an int and string to sip_msg
3482882Svi117747  */
3492882Svi117747 static int
sip_add_intstr_to_msg(sip_msg_t sip_msg,char * hdr_name,int i,char * s,char * plist)3502882Svi117747 sip_add_intstr_to_msg(sip_msg_t sip_msg, char *hdr_name, int i, char *s,
3512882Svi117747     char *plist)
3522882Svi117747 {
3532882Svi117747 	_sip_header_t	*new_header;
3542882Svi117747 	int 		header_size;
3552882Svi117747 	_sip_msg_t 	*_sip_msg;
3562882Svi117747 	char		*digit_str;
3572882Svi117747 	int		csize = sizeof (char);
3582882Svi117747 
3592882Svi117747 	if (sip_msg == NULL || (hdr_name == NULL))
3602882Svi117747 		return (EINVAL);
3612882Svi117747 	_sip_msg = (_sip_msg_t *)sip_msg;
3622882Svi117747 	(void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
3632882Svi117747 	if (_sip_msg->sip_msg_cannot_be_modified) {
3642882Svi117747 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
3652882Svi117747 		return (ENOTSUP);
3662882Svi117747 	}
3672882Svi117747 
3682882Svi117747 	/*
3692882Svi117747 	 * the following two loops convert int i to str
3702882Svi117747 	 */
3712882Svi117747 	digit_str = sip_int_to_str(i);
3722882Svi117747 	if (digit_str == NULL) {
3732882Svi117747 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
3742882Svi117747 		return (EINVAL);
3752882Svi117747 	}
3762882Svi117747 	if (plist == NULL) {
3772882Svi117747 		header_size = strlen(hdr_name) + SIP_SPACE_LEN + csize +
3782882Svi117747 		    SIP_SPACE_LEN + strlen(digit_str) + csize + strlen(s) +
3792882Svi117747 		    strlen(SIP_CRLF);
3802882Svi117747 	} else {
3812882Svi117747 		header_size = strlen(hdr_name) + SIP_SPACE_LEN + csize +
3822882Svi117747 		    SIP_SPACE_LEN + strlen(digit_str) + csize + strlen(s) +
3832882Svi117747 		    csize + strlen(plist) + strlen(SIP_CRLF);
3842882Svi117747 	}
3852882Svi117747 
3862882Svi117747 	new_header = sip_new_header(header_size);
3872882Svi117747 	if (new_header == NULL) {
3882882Svi117747 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
3892882Svi117747 		free(digit_str);
3902882Svi117747 		return (ENOMEM);
3912882Svi117747 	}
3922882Svi117747 
3932882Svi117747 	if (plist == NULL) {
3942882Svi117747 		(void) snprintf(new_header->sip_hdr_start, header_size + 1,
3952882Svi117747 		    "%s %c %s %s%s", hdr_name, SIP_HCOLON, digit_str, s,
3962882Svi117747 		    SIP_CRLF);
3972882Svi117747 	} else {
3982882Svi117747 		(void) snprintf(new_header->sip_hdr_start, header_size + 1,
3992882Svi117747 		    "%s %c %s %s%c%s%s", hdr_name, SIP_HCOLON, digit_str,
4002882Svi117747 		    s, SIP_SEMI, plist, SIP_CRLF);
4012882Svi117747 	}
4022882Svi117747 	free(digit_str);
4032882Svi117747 	_sip_add_header(_sip_msg, new_header, B_TRUE, B_FALSE, NULL);
4042882Svi117747 	if (_sip_msg->sip_msg_buf != NULL)
4052882Svi117747 		_sip_msg->sip_msg_modified = B_TRUE;
4062882Svi117747 	(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
4072882Svi117747 
4082882Svi117747 	return (0);
4092882Svi117747 }
4102882Svi117747 
4112882Svi117747 /*
4122882Svi117747  * Generic function to add Contact, From,  To, Route or Record-Route header
4132882Svi117747  */
4142882Svi117747 static int
sip_add_name_aspec(sip_msg_t sip_msg,char * display_name,char * uri,char * tags,boolean_t add_aquot,char * header_name,char * params)4152882Svi117747 sip_add_name_aspec(sip_msg_t sip_msg, char *display_name, char *uri,
4162882Svi117747     char *tags, boolean_t add_aquot, char *header_name, char *params)
4172882Svi117747 {
4182882Svi117747 	char		*t = uri;
4192882Svi117747 	boolean_t	qalloc = B_FALSE;
4202882Svi117747 	boolean_t	palloc = B_FALSE;
4212882Svi117747 	int		r;
4222882Svi117747 
4232882Svi117747 	if (sip_msg == NULL || uri == NULL || header_name == NULL)
4242882Svi117747 		return (EINVAL);
4252882Svi117747 	if (display_name != NULL && !add_aquot)
4262882Svi117747 		return (EINVAL);
4272882Svi117747 	if (add_aquot) {
4282882Svi117747 		t = sip_add_aquot_to_str(uri, &qalloc);
4292882Svi117747 		if (t == NULL)
4302882Svi117747 			return (ENOMEM);
4312882Svi117747 	}
4322882Svi117747 	if (tags != NULL) {
4332882Svi117747 		int	plen;
4342882Svi117747 
4352882Svi117747 		if (params != NULL)
4362882Svi117747 			return (EINVAL);
4372882Svi117747 
4382882Svi117747 		plen = strlen(SIP_TAG) + strlen(tags) + 1;
4392882Svi117747 		params = malloc(plen);
4402882Svi117747 		if (params == NULL)
4412882Svi117747 			return (ENOMEM);
4422882Svi117747 		(void) snprintf(params, plen, "%s%s", SIP_TAG, tags);
4432882Svi117747 		params[plen - 1] = '\0';
4442882Svi117747 		palloc = B_TRUE;
4452882Svi117747 	}
4462882Svi117747 	if (display_name == NULL) {
4472882Svi117747 		r = sip_add_2strs_to_msg(sip_msg, header_name, " ", B_FALSE,
4482882Svi117747 		    t, params, SIP_SP);
4492882Svi117747 	} else {
4502882Svi117747 		r = sip_add_2strs_to_msg(sip_msg, header_name, display_name,
4512882Svi117747 		    B_TRUE, t, params, SIP_SP);
4522882Svi117747 	}
4532882Svi117747 	if (qalloc)
4542882Svi117747 		free(t);
4552882Svi117747 	if (palloc)
4562882Svi117747 		free(params);
4572882Svi117747 	return (r);
4582882Svi117747 }
4592882Svi117747 
4602882Svi117747 /*
4612882Svi117747  * Accept = "Accept" ":" (media-range [ accept-params ])
4622882Svi117747  * media-range = ( "X/X" | (type "/" "*") | (type "/" subtype))*(";" parameter)
4632882Svi117747  * accept-params = ";" "q" "=" qvalue *(accept-extension)
4642882Svi117747  * accept-extension = ";" token [ "=" (token | quoted-str)
4652882Svi117747  *
4662882Svi117747  * function take two char ptrs - type and subtype - if any of them is NULL
4672882Svi117747  * the corresponding value will be set to "*" in header
4682882Svi117747  */
4692882Svi117747 int
sip_add_accept(sip_msg_t sip_msg,char * type,char * subtype,char * m_par,char * a_par)4702882Svi117747 sip_add_accept(sip_msg_t sip_msg, char *type, char *subtype, char *m_par,
4712882Svi117747     char *a_par)
4722882Svi117747 {
4732882Svi117747 	int		ret;
4742882Svi117747 	char		*plist;
4752882Svi117747 	int		size;
4762882Svi117747 	boolean_t	alloc = B_FALSE;
4772882Svi117747 
4782882Svi117747 	if (type == NULL && subtype == NULL) {
4792882Svi117747 		ret = sip_add_empty_hdr(sip_msg, SIP_ACCEPT);
4802882Svi117747 		return (ret);
4812882Svi117747 	}
4822882Svi117747 
4832882Svi117747 	if ((m_par != NULL) && (a_par != NULL)) {
4842882Svi117747 		size = strlen(m_par) + strlen(a_par) + 2 * sizeof (char);
4852882Svi117747 		plist = calloc(1, size * sizeof (char));
4862882Svi117747 		(void) strncpy(plist, m_par, strlen(m_par));
4872882Svi117747 		(void) strncat(plist, ";", 1);
4882882Svi117747 		(void) strncat(plist, a_par, strlen(a_par));
4892882Svi117747 		alloc = B_TRUE;
4902882Svi117747 	} else if (m_par != NULL) {
4912882Svi117747 		plist = m_par;
4922882Svi117747 	} else
4932882Svi117747 		plist = a_par;
4942882Svi117747 
4952882Svi117747 	if ((type != NULL) && (subtype != NULL)) {
4962882Svi117747 		ret = sip_add_2strs_to_msg(sip_msg, SIP_ACCEPT, type, B_FALSE,
4972882Svi117747 		    subtype, plist, SIP_SLASH);
4982882Svi117747 	} else if (type != NULL) {
4992882Svi117747 		ret = sip_add_2strs_to_msg(sip_msg, SIP_ACCEPT, type, B_FALSE,
5002882Svi117747 		    "*", plist, SIP_SLASH);
5012882Svi117747 	} else {
5022882Svi117747 		ret = EINVAL;
5032882Svi117747 	}
5042882Svi117747 
5052882Svi117747 	if (alloc == B_TRUE)
5062882Svi117747 		free(plist);
5072882Svi117747 
5082882Svi117747 	return (ret);
5092882Svi117747 }
5102882Svi117747 
5112882Svi117747 
5122882Svi117747 /*
5132882Svi117747  * Accept-Encoding = "Accept-Encoding" ":" 1#(codings [ ";" "q" "=" qval])
5142882Svi117747  * codings = ( content-coding | "*" )
5152882Svi117747  * content-coding   =  token
5162882Svi117747  *
5172882Svi117747  * function take one char ptr, if NULL value will be set to "*"
5182882Svi117747  */
5192882Svi117747 int
sip_add_accept_enc(sip_msg_t sip_msg,char * code,char * plist)5202882Svi117747 sip_add_accept_enc(sip_msg_t sip_msg, char *code, char *plist)
5212882Svi117747 {
5222882Svi117747 	int ret;
5232882Svi117747 
5242882Svi117747 	if (code == NULL) {
5252882Svi117747 		ret = sip_add_str_to_msg(sip_msg, SIP_ACCEPT_ENCODE, "*", plist,
5262882Svi117747 		    SIP_SEMI);
5272882Svi117747 	} else {
5282882Svi117747 		ret = sip_add_str_to_msg(sip_msg, SIP_ACCEPT_ENCODE, code,
5292882Svi117747 		    plist, SIP_SEMI);
5302882Svi117747 	}
5312882Svi117747 	return (ret);
5322882Svi117747 }
5332882Svi117747 
5342882Svi117747 /*
5352882Svi117747  * Accept-Language = "Accept-Language" ":" 1#( language-range [ ";" "q""=" val])
5362882Svi117747  * language-range = ( ( 1*8ALPHA *("-" 1*8ALPHA))|"*")
5372882Svi117747  */
5382882Svi117747 int
sip_add_accept_lang(sip_msg_t sip_msg,char * lang,char * plist)5392882Svi117747 sip_add_accept_lang(sip_msg_t sip_msg, char *lang, char *plist)
5402882Svi117747 {
5412882Svi117747 	int	ret;
5422882Svi117747 
5432882Svi117747 	if (lang == NULL) {
5442882Svi117747 		ret = sip_add_empty_hdr(sip_msg, SIP_ACCEPT_LANG);
5452882Svi117747 		return (ret);
5462882Svi117747 	}
5472882Svi117747 	ret = sip_add_str_to_msg(sip_msg, SIP_ACCEPT_LANG, lang, plist,
5482882Svi117747 	    SIP_SEMI);
5492882Svi117747 	return (ret);
5502882Svi117747 }
5512882Svi117747 
5522882Svi117747 /*
5532882Svi117747  * Alert-Info = "Alert-Info" ":" "<" URI ">"
5542882Svi117747  */
5552882Svi117747 int
sip_add_alert_info(sip_msg_t sip_msg,char * alert,char * plist)5562882Svi117747 sip_add_alert_info(sip_msg_t sip_msg, char *alert, char *plist)
5572882Svi117747 {
5582882Svi117747 	int		ret;
5592882Svi117747 	char		*tmp;
5602882Svi117747 	boolean_t	alloc;
5612882Svi117747 
5622882Svi117747 	if (alert == NULL)
5632882Svi117747 		return (EINVAL);
5642882Svi117747 	tmp = sip_add_aquot_to_str(alert, &alloc);
5652882Svi117747 	if (tmp == NULL)
5662882Svi117747 		return (ENOMEM);
5672882Svi117747 	ret = sip_add_str_to_msg(sip_msg, SIP_ALERT_INFO, tmp, plist, SIP_SEMI);
5682882Svi117747 	if (alloc)
5692882Svi117747 		free(tmp);
5702882Svi117747 	return (ret);
5712882Svi117747 }
5722882Svi117747 
5732882Svi117747 /*
5742882Svi117747  * Allow = "Allow" ":" method-name1[, method-name2..]
5752882Svi117747  * method-name = "INVITE" | "ACK" | "OPTIONS" | "CANCEL" | "BYE"
5762882Svi117747  */
5772882Svi117747 int
sip_add_allow(sip_msg_t sip_msg,sip_method_t method)5782882Svi117747 sip_add_allow(sip_msg_t sip_msg, sip_method_t method)
5792882Svi117747 {
5802882Svi117747 	int	ret;
5812882Svi117747 
5822882Svi117747 	if (method == 0 || method >= MAX_SIP_METHODS)
5832882Svi117747 		return (EINVAL);
5842882Svi117747 	ret = sip_add_str_to_msg(sip_msg, SIP_ALLOW, sip_methods[method].name,
5852882Svi117747 	    NULL, (char)NULL);
5862882Svi117747 	return (ret);
5872882Svi117747 }
5882882Svi117747 
5892882Svi117747 /*
5902882Svi117747  * Call-Info   =  "Call-Info" HCOLON info *(COMMA info)
5912882Svi117747  * info        =  LAQUOT absoluteURI RAQUOT *( SEMI info-param)
5922882Svi117747  * info-param  =  ( "purpose" EQUAL ( "icon" / "info"
5932882Svi117747  *		/ "card" / token ) ) / generic-param
5942882Svi117747  */
5952882Svi117747 int
sip_add_call_info(sip_msg_t sip_msg,char * uri,char * plist)5962882Svi117747 sip_add_call_info(sip_msg_t sip_msg, char *uri, char *plist)
5972882Svi117747 {
5982882Svi117747 	char		*tmp;
5992882Svi117747 	boolean_t	alloc;
6002882Svi117747 	int		r;
6012882Svi117747 
6022882Svi117747 	if (uri == NULL)
6032882Svi117747 		return (EINVAL);
6042882Svi117747 	tmp = sip_add_aquot_to_str(uri, &alloc);
6052882Svi117747 	if (tmp == NULL)
6062882Svi117747 		return (ENOMEM);
6072882Svi117747 	r = sip_add_str_to_msg(sip_msg, SIP_CALL_INFO, tmp, plist, SIP_SEMI);
6082882Svi117747 	if (alloc)
6092882Svi117747 		free(tmp);
6102882Svi117747 	return (r);
6112882Svi117747 }
6122882Svi117747 
6132882Svi117747 /*
6142882Svi117747  * Content-Disposition   =  "Content-Disposition" HCOLON
6152882Svi117747  *				disp-type *( SEMI disp-param )
6162882Svi117747  * disp-type             =  "render" / "session" / "icon" / "alert"
6172882Svi117747  *				/ disp-extension-token
6182882Svi117747  * disp-param            =  handling-param / generic-param
6192882Svi117747  * handling-param        =  "handling" EQUAL
6202882Svi117747  *				( "optional" / "required"
6212882Svi117747  *				/ other-handling )
6222882Svi117747  * other-handling        =  token
6232882Svi117747  * disp-extension-token  =  token
6242882Svi117747  */
6252882Svi117747 int
sip_add_content_disp(sip_msg_t sip_msg,char * dis_type,char * plist)6262882Svi117747 sip_add_content_disp(sip_msg_t sip_msg, char *dis_type, char *plist)
6272882Svi117747 {
6282882Svi117747 	int	ret;
6292882Svi117747 
6302882Svi117747 	if (dis_type == NULL)
6312882Svi117747 		return (EINVAL);
6322882Svi117747 
6332882Svi117747 	ret = sip_add_str_to_msg(sip_msg, SIP_CONTENT_DIS, dis_type, plist,
6342882Svi117747 	    SIP_SEMI);
6352882Svi117747 	return (ret);
6362882Svi117747 }
6372882Svi117747 
6382882Svi117747 /*
6392882Svi117747  * Content-Encoding  =  ( "Content-Encoding" / "e" ) HCOLON
6402882Svi117747  *			content-coding *(COMMA content-coding)
6412882Svi117747  * content-coding   =  token
6422882Svi117747  */
6432882Svi117747 int
sip_add_content_enc(sip_msg_t sip_msg,char * code)6442882Svi117747 sip_add_content_enc(sip_msg_t sip_msg, char *code)
6452882Svi117747 {
6462882Svi117747 	int	ret;
6472882Svi117747 
6482882Svi117747 	if (code == NULL)
6492882Svi117747 		return (EINVAL);
6502882Svi117747 
6512882Svi117747 	ret = sip_add_str_to_msg(sip_msg, SIP_CONTENT_ENCODE, code, NULL,
6522882Svi117747 	    (char)NULL);
6532882Svi117747 	return (ret);
6542882Svi117747 }
6552882Svi117747 
6562882Svi117747 /*
6572882Svi117747  * Content-Language  =  "Content-Language" HCOLON
6582882Svi117747  *			language-tag *(COMMA language-tag)
6592882Svi117747  * language-tag      =  primary-tag *( "-" subtag )
6602882Svi117747  * primary-tag       =  1*8ALPHA
6612882Svi117747  * subtag            =  1*8ALPHA
6622882Svi117747  */
6632882Svi117747 int
sip_add_content_lang(sip_msg_t sip_msg,char * lang)6642882Svi117747 sip_add_content_lang(sip_msg_t sip_msg, char *lang)
6652882Svi117747 {
6662882Svi117747 	int	ret;
6672882Svi117747 
6682882Svi117747 	if (lang == NULL)
6692882Svi117747 		return (EINVAL);
6702882Svi117747 	ret = sip_add_str_to_msg(sip_msg, SIP_CONTENT_LANG, lang, NULL,
6712882Svi117747 	    (char)NULL);
6722882Svi117747 	return (ret);
6732882Svi117747 }
6742882Svi117747 
6752882Svi117747 /*
6762882Svi117747  * Date          =  "Date" HCOLON SIP-date
6772882Svi117747  * SIP-date      =  rfc1123-date
6782882Svi117747  * rfc1123-date  =  wkday "," SP date1 SP time SP "GMT"
6792882Svi117747  * date1         =  2DIGIT SP month SP 4DIGIT
6802882Svi117747  * 			; day month year (e.g., 02 Jun 1982)
6812882Svi117747  * time          =  2DIGIT ":" 2DIGIT ":" 2DIGIT
6822882Svi117747  *			; 00:00:00 - 23:59:59
6832882Svi117747  * wkday         =  "Mon" / "Tue" / "Wed"
6842882Svi117747  *			/ "Thu" / "Fri" / "Sat" / "Sun"
6852882Svi117747  * month         =  "Jan" / "Feb" / "Mar" / "Apr"
6862882Svi117747  *			/ "May" / "Jun" / "Jul" / "Aug"
6872882Svi117747  *			/ "Sep" / "Oct" / "Nov" / "Dec"
6882882Svi117747  */
6892882Svi117747 int
sip_add_date(sip_msg_t sip_msg,char * date)6902882Svi117747 sip_add_date(sip_msg_t sip_msg, char *date)
6912882Svi117747 {
6922882Svi117747 	int	ret;
6932882Svi117747 
6942882Svi117747 	if (date == NULL)
6952882Svi117747 		return (EINVAL);
6962882Svi117747 	ret = sip_add_str_to_msg(sip_msg, SIP_DATE, date, NULL, (char)NULL);
6972882Svi117747 	return (ret);
6982882Svi117747 }
6992882Svi117747 
7002882Svi117747 /*
7012882Svi117747  * Error-Info  =  "Error-Info" HCOLON error-uri *(COMMA error-uri)
7022882Svi117747  * error-uri   =  LAQUOT absoluteURI RAQUOT *( SEMI generic-param )
7032882Svi117747  */
7042882Svi117747 int
sip_add_error_info(sip_msg_t sip_msg,char * uri,char * plist)7052882Svi117747 sip_add_error_info(sip_msg_t sip_msg, char *uri, char *plist)
7062882Svi117747 {
7072882Svi117747 	char		*tmp;
7082882Svi117747 	boolean_t	alloc;
7092882Svi117747 	int		r;
7102882Svi117747 
7112882Svi117747 	if (uri == NULL)
7122882Svi117747 		return (EINVAL);
7132882Svi117747 	tmp = sip_add_aquot_to_str(uri, &alloc);
7142882Svi117747 	if (tmp == NULL)
7152882Svi117747 		return (EINVAL);
7162882Svi117747 
7172882Svi117747 	r = sip_add_str_to_msg(sip_msg, SIP_ERROR_INFO, tmp, plist, SIP_SEMI);
7182882Svi117747 	if (alloc)
7192882Svi117747 		free(tmp);
7202882Svi117747 	return (r);
7212882Svi117747 }
7222882Svi117747 
7232882Svi117747 /*
7242882Svi117747  * Expires     =  "Expires" HCOLON delta-seconds
7252882Svi117747  * delta-seconds      =  1*DIGIT
7262882Svi117747  */
7272882Svi117747 int
sip_add_expires(sip_msg_t sip_msg,int secs)7282882Svi117747 sip_add_expires(sip_msg_t sip_msg, int secs)
7292882Svi117747 {
7302882Svi117747 	int	ret;
7312882Svi117747 
7322882Svi117747 	if (sip_msg == NULL || (int)secs < 0)
7332882Svi117747 		return (EINVAL);
7342882Svi117747 
7352882Svi117747 	ret = sip_add_int_to_msg(sip_msg, SIP_EXPIRE, secs, NULL);
7362882Svi117747 	return (ret);
7372882Svi117747 }
7382882Svi117747 
7392882Svi117747 /*
7402882Svi117747  * In-Reply-To  =  "In-Reply-To" HCOLON callid *(COMMA callid)
7412882Svi117747  * callid   =  word [ "@" word ]
7422882Svi117747  */
7432882Svi117747 int
sip_add_in_reply_to(sip_msg_t sip_msg,char * reply_id)7442882Svi117747 sip_add_in_reply_to(sip_msg_t sip_msg, char *reply_id)
7452882Svi117747 {
7462882Svi117747 	int		r;
7472882Svi117747 
7482882Svi117747 	if (reply_id == NULL)
7492882Svi117747 		return (EINVAL);
7502882Svi117747 	r = sip_add_str_to_msg(sip_msg, SIP_IN_REPLY_TO, reply_id, NULL,
7512882Svi117747 	    (char)NULL);
7522882Svi117747 	return (r);
7532882Svi117747 }
7542882Svi117747 
7552882Svi117747 /*
7562882Svi117747  * RSeq          =  "RSeq" HCOLON response-num
7572882Svi117747  */
7582882Svi117747 int
sip_add_rseq(sip_msg_t sip_msg,int resp_num)7592882Svi117747 sip_add_rseq(sip_msg_t sip_msg, int resp_num)
7602882Svi117747 {
7612882Svi117747 	int	ret;
7622882Svi117747 
7632882Svi117747 	if (sip_msg == NULL || resp_num <= 0)
7642882Svi117747 		return (EINVAL);
7652882Svi117747 	ret = sip_add_int_to_msg(sip_msg, SIP_RSEQ, resp_num, NULL);
7662882Svi117747 	return (ret);
7672882Svi117747 }
7682882Svi117747 
7692882Svi117747 /*
7702882Svi117747  * Min-Expires  =  "Min-Expires" HCOLON delta-seconds
7712882Svi117747  */
7722882Svi117747 int
sip_add_min_expires(sip_msg_t sip_msg,int secs)7732882Svi117747 sip_add_min_expires(sip_msg_t sip_msg, int secs)
7742882Svi117747 {
7752882Svi117747 	int	ret;
7762882Svi117747 
7772882Svi117747 	if (sip_msg == NULL || (int)secs < 0)
7782882Svi117747 		return (EINVAL);
7792882Svi117747 	ret = sip_add_int_to_msg(sip_msg, SIP_MIN_EXPIRE, secs, NULL);
7802882Svi117747 	return (ret);
7812882Svi117747 }
7822882Svi117747 
7832882Svi117747 /*
7842882Svi117747  * MIME-Version  =  "MIME-Version" HCOLON 1*DIGIT "." 1*DIGIT
7852882Svi117747  */
7862882Svi117747 int
sip_add_mime_version(sip_msg_t sip_msg,char * version)7872882Svi117747 sip_add_mime_version(sip_msg_t sip_msg, char *version)
7882882Svi117747 {
7892882Svi117747 	int	ret;
7902882Svi117747 
7912882Svi117747 	if (version == NULL)
7922882Svi117747 		return (EINVAL);
7932882Svi117747 	ret = sip_add_str_to_msg(sip_msg, SIP_MIME_VERSION, version, NULL,
7942882Svi117747 	    (char)NULL);
7952882Svi117747 	return (ret);
7962882Svi117747 }
7972882Svi117747 
7982882Svi117747 /*
7992882Svi117747  * Organization  =  "Organization" HCOLON [TEXT-UTF8-TRIM]
8002882Svi117747  */
8012882Svi117747 int
sip_add_org(sip_msg_t sip_msg,char * org)8022882Svi117747 sip_add_org(sip_msg_t sip_msg, char *org)
8032882Svi117747 {
8042882Svi117747 	int	ret;
8052882Svi117747 
8062882Svi117747 	if (org == NULL) {
8072882Svi117747 		ret = sip_add_empty_hdr(sip_msg, SIP_ORGANIZATION);
8082882Svi117747 	} else {
8092882Svi117747 		ret = sip_add_str_to_msg(sip_msg, SIP_ORGANIZATION, org, NULL,
8102882Svi117747 		    (char)NULL);
8112882Svi117747 	}
8122882Svi117747 	return (ret);
8132882Svi117747 }
8142882Svi117747 
8152882Svi117747 /*
8162882Svi117747  * Priority        =  "Priority" HCOLON priority-value
8172882Svi117747  * priority-value  =  "emergency" / "urgent" / "normal"
8182882Svi117747  *			/ "non-urgent" / other-priority
8192882Svi117747  * other-priority  =  token
8202882Svi117747  */
8212882Svi117747 int
sip_add_priority(sip_msg_t sip_msg,char * prio)8222882Svi117747 sip_add_priority(sip_msg_t sip_msg, char *prio)
8232882Svi117747 {
8242882Svi117747 	int	ret;
8252882Svi117747 
8262882Svi117747 	if (prio == NULL)
8272882Svi117747 		return (EINVAL);
8282882Svi117747 	ret = sip_add_str_to_msg(sip_msg, SIP_PRIORITY, prio, NULL, (char)NULL);
8292882Svi117747 
8302882Svi117747 	return (ret);
8312882Svi117747 }
8322882Svi117747 
8332882Svi117747 /*
8342882Svi117747  * Reply-To      =  "Reply-To" HCOLON rplyto-spec
8352882Svi117747  * rplyto-spec   =  ( name-addr / addr-spec )
8362882Svi117747  *			*( SEMI rplyto-param )
8372882Svi117747  * rplyto-param  =  generic-param
8382882Svi117747  */
8392882Svi117747 int
sip_add_reply_to(sip_msg_t sip_msg,char * uname,char * addr,char * plist,boolean_t add_aquot)8402882Svi117747 sip_add_reply_to(sip_msg_t sip_msg, char *uname, char *addr, char *plist,
8412882Svi117747     boolean_t add_aquot)
8422882Svi117747 {
8432882Svi117747 	return (sip_add_name_aspec(sip_msg, uname, addr, NULL, add_aquot,
8442882Svi117747 	    SIP_REPLYTO, plist));
8452882Svi117747 }
8462882Svi117747 
8472882Svi117747 
8482882Svi117747 /*
8492882Svi117747  * Privacy-hdr  =  "Privacy" HCOLON priv-value *(";" priv-value)
8502882Svi117747  * priv-value   =   "header" / "session" / "user" / "none" / "critical"
8512882Svi117747  *			/ token
8522882Svi117747  */
8532882Svi117747 int
sip_add_privacy(sip_msg_t sip_msg,char * priv_val)8542882Svi117747 sip_add_privacy(sip_msg_t sip_msg, char *priv_val)
8552882Svi117747 {
8562882Svi117747 	int	ret;
8572882Svi117747 
8582882Svi117747 	if (priv_val == NULL)
8592882Svi117747 		return (EINVAL);
8602882Svi117747 	ret = sip_add_str_to_msg(sip_msg, SIP_PRIVACY, priv_val, NULL,
8612882Svi117747 	    (char)NULL);
8622882Svi117747 	return (ret);
8632882Svi117747 }
8642882Svi117747 
8652882Svi117747 /*
8662882Svi117747  * Require       =  "Require" HCOLON option-tag *(COMMA option-tag)
8672882Svi117747  * option-tag     =  token
8682882Svi117747  */
8692882Svi117747 int
sip_add_require(sip_msg_t sip_msg,char * req)8702882Svi117747 sip_add_require(sip_msg_t sip_msg, char *req)
8712882Svi117747 {
8722882Svi117747 	int	ret;
8732882Svi117747 
8742882Svi117747 	if (req == NULL)
8752882Svi117747 		return (EINVAL);
8762882Svi117747 	ret = sip_add_str_to_msg(sip_msg, SIP_REQUIRE, req, NULL, (char)NULL);
8772882Svi117747 	return (ret);
8782882Svi117747 }
8792882Svi117747 
8802882Svi117747 /*
8812882Svi117747  * Retry-After  =  "Retry-After" HCOLON delta-seconds
8822882Svi117747  *			[ comment ] *( SEMI retry-param )
8832882Svi117747  * retry-param  =  ("duration" EQUAL delta-seconds)
8842882Svi117747  *			/ generic-param
8852882Svi117747  */
8862882Svi117747 int
sip_add_retry_after(sip_msg_t sip_msg,int secs,char * cmt,char * plist)8872882Svi117747 sip_add_retry_after(sip_msg_t sip_msg, int secs, char *cmt, char *plist)
8882882Svi117747 {
8892882Svi117747 	int	r;
8902882Svi117747 
8912882Svi117747 	if (secs <= 0)
8922882Svi117747 		return (EINVAL);
8932882Svi117747 
8942882Svi117747 	if (cmt == NULL) {
8952882Svi117747 		r = sip_add_int_to_msg(sip_msg, SIP_RETRY_AFTER, secs, plist);
8962882Svi117747 		return (r);
8972882Svi117747 	}
8982882Svi117747 
8992882Svi117747 	r = sip_add_intstr_to_msg(sip_msg, SIP_RETRY_AFTER, secs, cmt, plist);
9002882Svi117747 	return (r);
9012882Svi117747 }
9022882Svi117747 
9032882Svi117747 /*
9042882Svi117747  * Server           =  "Server" HCOLON server-val *(LWS server-val)
9052882Svi117747  * server-val       =  product / comment
9062882Svi117747  * product          =  token [SLASH product-version]
9072882Svi117747  * product-version  =  token
9082882Svi117747  */
9092882Svi117747 int
sip_add_server(sip_msg_t sip_msg,char * svr)9102882Svi117747 sip_add_server(sip_msg_t sip_msg, char *svr)
9112882Svi117747 {
9122882Svi117747 	int	ret;
9132882Svi117747 
9142882Svi117747 	if (svr == NULL)
9152882Svi117747 		return (EINVAL);
9162882Svi117747 	ret = sip_add_str_to_msg(sip_msg, SIP_SERVER, svr, NULL, (char)NULL);
9172882Svi117747 	return (ret);
9182882Svi117747 }
9192882Svi117747 
9202882Svi117747 /*
9212882Svi117747  * Subject  =  ( "Subject" / "s" ) HCOLON [TEXT-UTF8-TRIM]
9222882Svi117747  */
9232882Svi117747 int
sip_add_subject(sip_msg_t sip_msg,char * subject)9242882Svi117747 sip_add_subject(sip_msg_t sip_msg, char *subject)
9252882Svi117747 {
9262882Svi117747 	int	ret;
9272882Svi117747 
9282882Svi117747 	if (subject == NULL) {
9292882Svi117747 		ret = sip_add_empty_hdr(sip_msg, SIP_SUBJECT);
9302882Svi117747 	} else {
9312882Svi117747 		ret = sip_add_str_to_msg(sip_msg, SIP_SUBJECT, subject, NULL,
9322882Svi117747 		    (char)NULL);
9332882Svi117747 	}
9342882Svi117747 	return (ret);
9352882Svi117747 }
9362882Svi117747 
9372882Svi117747 /*
9382882Svi117747  * Supported  =  ( "Supported" / "k" ) HCOLON
9392882Svi117747  *		[option-tag *(COMMA option-tag)]
9402882Svi117747  */
9412882Svi117747 int
sip_add_supported(sip_msg_t sip_msg,char * support)9422882Svi117747 sip_add_supported(sip_msg_t sip_msg, char *support)
9432882Svi117747 {
9442882Svi117747 	int	ret;
9452882Svi117747 
9462882Svi117747 	if (support == NULL) {
9472882Svi117747 		ret = sip_add_empty_hdr(sip_msg, SIP_SUPPORT);
9482882Svi117747 	} else {
9492882Svi117747 		ret = sip_add_str_to_msg(sip_msg, SIP_SUPPORT, support, NULL,
9502882Svi117747 		    (char)NULL);
9512882Svi117747 	}
9522882Svi117747 	return (ret);
9532882Svi117747 }
9542882Svi117747 
9552882Svi117747 /*
9562882Svi117747  * Timestamp  =  "Timestamp" HCOLON 1*(DIGIT)
9572882Svi117747  *		[ "." *(DIGIT) ] [ LWS delay ]
9582882Svi117747  * delay      =  *(DIGIT) [ "." *(DIGIT) ]
9592882Svi117747  */
9602882Svi117747 int
sip_add_tstamp(sip_msg_t sip_msg,char * time,char * delay)9612882Svi117747 sip_add_tstamp(sip_msg_t sip_msg, char *time, char *delay)
9622882Svi117747 {
9632882Svi117747 	int	ret;
9642882Svi117747 
9652882Svi117747 	if (delay == NULL) {
9662882Svi117747 		ret = sip_add_str_to_msg(sip_msg, SIP_TIMESTAMP, time, NULL,
9672882Svi117747 		    (char)NULL);
9682882Svi117747 	} else {
9692882Svi117747 		ret = sip_add_2strs_to_msg(sip_msg, SIP_TIMESTAMP, time,
9702882Svi117747 		    B_FALSE, delay, NULL, ' ');
9712882Svi117747 	}
9722882Svi117747 	return (ret);
9732882Svi117747 }
9742882Svi117747 
9752882Svi117747 /*
9762882Svi117747  * Unsupported  =  "Unsupported" HCOLON option-tag *(COMMA option-tag)
9772882Svi117747  */
9782882Svi117747 int
sip_add_unsupported(sip_msg_t sip_msg,char * unsupport)9792882Svi117747 sip_add_unsupported(sip_msg_t sip_msg, char *unsupport)
9802882Svi117747 {
9812882Svi117747 	int	ret;
9822882Svi117747 
9832882Svi117747 	if (unsupport == NULL)
9842882Svi117747 		return (EINVAL);
9852882Svi117747 	ret = sip_add_str_to_msg(sip_msg, SIP_UNSUPPORT, unsupport, NULL,
9862882Svi117747 	    (char)NULL);
9872882Svi117747 	return (ret);
9882882Svi117747 }
9892882Svi117747 
9902882Svi117747 /*
9912882Svi117747  * User-Agent  =  "User-Agent" HCOLON server-val *(LWS server-val)
9922882Svi117747  */
9932882Svi117747 int
sip_add_user_agent(sip_msg_t sip_msg,char * usr)9942882Svi117747 sip_add_user_agent(sip_msg_t sip_msg, char *usr)
9952882Svi117747 {
9962882Svi117747 	int	r;
9972882Svi117747 
9982882Svi117747 	if (usr == NULL)
9992882Svi117747 		return (EINVAL);
10002882Svi117747 	r = sip_add_str_to_msg(sip_msg, SIP_USER_AGENT, usr, NULL, (char)NULL);
10012882Svi117747 	return (r);
10022882Svi117747 }
10032882Svi117747 
10042882Svi117747 /*
10052882Svi117747  * Warning        =  "Warning" HCOLON warning-value *(COMMA warning-value)
10062882Svi117747  * warning-value  =  warn-code SP warn-agent SP warn-text
10072882Svi117747  * warn-code      =  3DIGIT
10082882Svi117747  * warn-agent     =  hostport / pseudonym
10092882Svi117747  *			;  the name or pseudonym of the server adding
10102882Svi117747  *			;  the Warning header, for use in debugging
10112882Svi117747  * warn-text      =  quoted-string
10122882Svi117747  * pseudonym      =  token
10132882Svi117747  */
10142882Svi117747 int
sip_add_warning(sip_msg_t sip_msg,int code,char * addr,char * msg)10152882Svi117747 sip_add_warning(sip_msg_t sip_msg, int code, char *addr, char *msg)
10162882Svi117747 {
10172882Svi117747 	_sip_header_t	*new_header;
10182882Svi117747 	int 		header_size;
10192882Svi117747 	_sip_msg_t 	*_sip_msg;
10202882Svi117747 	char		*hdr_name = SIP_WARNING;
10212882Svi117747 
10222882Svi117747 	if (sip_msg == NULL || addr == NULL || msg == NULL ||
10232882Svi117747 	    addr[0] == '\0' || msg == '\0' || code < 100 || code > 999) {
10242882Svi117747 		return (EINVAL);
10252882Svi117747 	}
10262882Svi117747 
10272882Svi117747 	_sip_msg = (_sip_msg_t *)sip_msg;
10282882Svi117747 	(void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
10292882Svi117747 	if (_sip_msg->sip_msg_cannot_be_modified) {
10302882Svi117747 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
10312882Svi117747 		return (ENOTSUP);
10322882Svi117747 	}
10332882Svi117747 
10342882Svi117747 	header_size = strlen(hdr_name) + SIP_SPACE_LEN + sizeof (char) +
10352882Svi117747 	    SIP_SPACE_LEN + sip_num_of_digits(code) + SIP_SPACE_LEN +
10362882Svi117747 	    strlen(addr) + SIP_SPACE_LEN + sizeof (char) + strlen(msg) +
10372882Svi117747 	    sizeof (char) + strlen(SIP_CRLF);
10382882Svi117747 
10392882Svi117747 	new_header = sip_new_header(header_size);
10402882Svi117747 	if (new_header == NULL) {
10412882Svi117747 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
10422882Svi117747 		return (ENOMEM);
10432882Svi117747 	}
10442882Svi117747 
10452882Svi117747 	(void) snprintf(new_header->sip_hdr_start, header_size + 1,
10462882Svi117747 	    "%s %c %d %s \"%s\"%s", hdr_name, SIP_HCOLON, code, addr,
10472882Svi117747 	    msg, SIP_CRLF);
10482882Svi117747 	_sip_add_header(_sip_msg, new_header, B_TRUE, B_FALSE, NULL);
10492882Svi117747 	if (_sip_msg->sip_msg_buf != NULL)
10502882Svi117747 		_sip_msg->sip_msg_modified = B_TRUE;
10512882Svi117747 	(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
10522882Svi117747 
10532882Svi117747 	return (0);
10542882Svi117747 }
10552882Svi117747 
10562882Svi117747 /*
10572882Svi117747  * RAck          =  "RAck" HCOLON response-num LWS CSeq-num LWS Method
10582882Svi117747  * response-num  =  1*DIGIT
10592882Svi117747  * CSeq-num      =  1*DIGIT
10602882Svi117747  */
10612882Svi117747 int
sip_add_rack(sip_msg_t sip_msg,int resp_num,int cseq,sip_method_t method)10622882Svi117747 sip_add_rack(sip_msg_t sip_msg, int resp_num, int cseq, sip_method_t method)
10632882Svi117747 {
10642882Svi117747 	_sip_header_t	*new_header;
10652882Svi117747 	int 		header_size;
10662882Svi117747 	_sip_msg_t 	*_sip_msg;
10672882Svi117747 	char		*hdr_name = SIP_RACK;
10682882Svi117747 
10692882Svi117747 	if (sip_msg == NULL || resp_num <= 0 || cseq < 0 || method <= 0 ||
10702882Svi117747 	    method >= MAX_SIP_METHODS) {
10712882Svi117747 		return (EINVAL);
10722882Svi117747 	}
10732882Svi117747 
10742882Svi117747 	_sip_msg = (_sip_msg_t *)sip_msg;
10752882Svi117747 	(void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
10762882Svi117747 	if (_sip_msg->sip_msg_cannot_be_modified) {
10772882Svi117747 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
10782882Svi117747 		return (ENOTSUP);
10792882Svi117747 	}
10802882Svi117747 
10812882Svi117747 	header_size = strlen(hdr_name) + SIP_SPACE_LEN + sizeof (char) +
10822882Svi117747 	    SIP_SPACE_LEN + sip_num_of_digits(resp_num) + SIP_SPACE_LEN +
10832882Svi117747 	    sip_num_of_digits(cseq) + SIP_SPACE_LEN +
10842882Svi117747 	    strlen(sip_methods[method].name) + strlen(SIP_CRLF);
10852882Svi117747 
10862882Svi117747 	new_header = sip_new_header(header_size);
10872882Svi117747 	if (new_header == NULL) {
10882882Svi117747 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
10892882Svi117747 		return (ENOMEM);
10902882Svi117747 	}
10912882Svi117747 
10922882Svi117747 	(void) snprintf(new_header->sip_hdr_start, header_size + 1,
10932882Svi117747 	    "%s %c %d %d %s%s", hdr_name, SIP_HCOLON, resp_num, cseq,
10942882Svi117747 	    sip_methods[method].name, SIP_CRLF);
10952882Svi117747 
10962882Svi117747 	_sip_add_header(_sip_msg, new_header, B_TRUE, B_FALSE, NULL);
10972882Svi117747 	if (_sip_msg->sip_msg_buf != NULL)
10982882Svi117747 		_sip_msg->sip_msg_modified = B_TRUE;
10992882Svi117747 	(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
11002882Svi117747 
11012882Svi117747 	return (0);
11022882Svi117747 
11032882Svi117747 }
11042882Svi117747 
11052882Svi117747 /*
11062882Svi117747  * Allow-Events =  ( "Allow-Events" / "u" ) HCOLON event-type
11072882Svi117747  *			*(COMMA event-type)
11082882Svi117747  */
11092882Svi117747 int
sip_add_allow_events(sip_msg_t sip_msg,char * t_event)11102882Svi117747 sip_add_allow_events(sip_msg_t sip_msg, char *t_event)
11112882Svi117747 {
11122882Svi117747 	return (sip_add_str_to_msg(sip_msg, SIP_ALLOW_EVENTS, t_event, NULL,
11132882Svi117747 	    (char)NULL));
11142882Svi117747 }
11152882Svi117747 
11162882Svi117747 /*
11172882Svi117747  * Event             =  ( "Event" / "o" ) HCOLON event-type
11182882Svi117747  *			*( SEMI event-param )
11192882Svi117747  * event-type        =  event-package *( "." event-template )
11202882Svi117747  * event-package     =  token-nodot
11212882Svi117747  * event-template    =  token-nodot
11222882Svi117747  * token-nodot       =  1*( alphanum / "-"  / "!" / "%" / "*"
11232882Svi117747  *			/ "_" / "+" / "`" / "'" / "~" )
11242882Svi117747  * event-param       =  generic-param / ( "id" EQUAL token )
11252882Svi117747  */
11262882Svi117747 int
sip_add_event(sip_msg_t sip_msg,char * t_event,char * plist)11272882Svi117747 sip_add_event(sip_msg_t sip_msg, char *t_event, char *plist)
11282882Svi117747 {
11292882Svi117747 	return (sip_add_str_to_msg(sip_msg, SIP_EVENT, t_event, plist,
11302882Svi117747 	    SIP_SEMI));
11312882Svi117747 }
11322882Svi117747 
11332882Svi117747 /*
11342882Svi117747  * Subscription-State   = "Subscription-State" HCOLON substate-value
11352882Svi117747  * 			*( SEMI subexp-params )
11362882Svi117747  * substate-value       = "active" / "pending" / "terminated"
11372882Svi117747  *			/ extension-substate
11382882Svi117747  * extension-substate   = token
11392882Svi117747  * subexp-params        =   ("reason" EQUAL event-reason-value)
11402882Svi117747  *			/ ("expires" EQUAL delta-seconds)*
11412882Svi117747  * 			/ ("retry-after" EQUAL delta-seconds)
11422882Svi117747  *			/ generic-param
11432882Svi117747  * event-reason-value   =   "deactivated"
11442882Svi117747  *				/ "probation"
11452882Svi117747  *				/ "rejected"
11462882Svi117747  *				/ "timeout"
11472882Svi117747  *				/ "giveup"
11482882Svi117747  *				/ "noresource"
11492882Svi117747  *				/ event-reason-extension
11502882Svi117747  * event-reason-extension = token
11512882Svi117747  */
11522882Svi117747 int
sip_add_substate(sip_msg_t sip_msg,char * sub,char * plist)11532882Svi117747 sip_add_substate(sip_msg_t sip_msg, char *sub, char *plist)
11542882Svi117747 {
11552882Svi117747 	return (sip_add_str_to_msg(sip_msg, SIP_SUBSCRIPTION_STATE, sub, plist,
11562882Svi117747 	    SIP_SEMI));
11572882Svi117747 }
11582882Svi117747 
11592882Svi117747 /*
11602882Svi117747  * Authorization     =  "Authorization" HCOLON credentials
11612882Svi117747  * credentials       =  ("Digest" LWS digest-response)
11622882Svi117747  *			/ other-response
11632882Svi117747  * digest-response   =  dig-resp *(COMMA dig-resp)
11642882Svi117747  * dig-resp          =  username / realm / nonce / digest-uri
11652882Svi117747  *			/ dresponse / algorithm / cnonce
11662882Svi117747  *			/ opaque / message-qop
11672882Svi117747  *			/ nonce-count / auth-param
11682882Svi117747  * username          =  "username" EQUAL username-value
11692882Svi117747  * username-value    =  quoted-string
11702882Svi117747  * digest-uri        =  "uri" EQUAL LDQUOT digest-uri-value RDQUOT
11712882Svi117747  * digest-uri-value  =  rquest-uri ; Equal to request-uri as specified
11722882Svi117747  *			by HTTP/1.1
11732882Svi117747  * message-qop       =  "qop" EQUAL qop-value
11742882Svi117747  * cnonce            =  "cnonce" EQUAL cnonce-value
11752882Svi117747  * cnonce-value      =  nonce-value
11762882Svi117747  * nonce-count       =  "nc" EQUAL nc-value
11772882Svi117747  * nc-value          =  8LHEX
11782882Svi117747  * dresponse         =  "response" EQUAL request-digest
11792882Svi117747  * request-digest    =  LDQUOT 32LHEX RDQUOT
11802882Svi117747  * auth-param        =  auth-param-name EQUAL
11812882Svi117747  * 			( token / quoted-string )
11822882Svi117747  * auth-param-name   =  token
11832882Svi117747  * other-response    =  auth-scheme LWS auth-param
11842882Svi117747  *			*(COMMA auth-param)
11852882Svi117747  * auth-scheme       =  token
11862882Svi117747  */
11872882Svi117747 int
sip_add_author(sip_msg_t sip_msg,char * scheme,char * param)11882882Svi117747 sip_add_author(sip_msg_t sip_msg, char *scheme, char *param)
11892882Svi117747 {
11902882Svi117747 	return (sip_add_str_to_msg(sip_msg, SIP_AUTHOR, scheme, param, SIP_SP));
11912882Svi117747 }
11922882Svi117747 
11932882Svi117747 /*
11942882Svi117747  * Authentication-Info  =  "Authentication-Info" HCOLON ainfo
11952882Svi117747  *				*(COMMA ainfo)
11962882Svi117747  * ainfo                =  nextnonce / message-qop
11972882Svi117747  *				/ response-auth / cnonce
11982882Svi117747  *				/ nonce-count
11992882Svi117747  * nextnonce            =  "nextnonce" EQUAL nonce-value
12002882Svi117747  * response-auth        =  "rspauth" EQUAL response-digest
12012882Svi117747  * response-digest      =  LDQUOT *LHEX RDQUOT
12022882Svi117747  */
12032882Svi117747 int
sip_add_authen_info(sip_msg_t sip_msg,char * ainfo)12042882Svi117747 sip_add_authen_info(sip_msg_t sip_msg, char *ainfo)
12052882Svi117747 {
12062882Svi117747 	return (sip_add_str_to_msg(sip_msg, SIP_AUTHEN_INFO, ainfo, NULL,
12072882Svi117747 	    (char)NULL));
12082882Svi117747 }
12092882Svi117747 
12102882Svi117747 /*
12112882Svi117747  * Proxy-Authenticate  =  "Proxy-Authenticate" HCOLON challenge
12122882Svi117747  * challenge           =  ("Digest" LWS digest-cln *(COMMA digest-cln))
12132882Svi117747  *				/ other-challenge
12142882Svi117747  * other-challenge     =  auth-scheme LWS auth-param
12152882Svi117747  * 				*(COMMA auth-param)
12162882Svi117747  * digest-cln          =  realm / domain / nonce
12172882Svi117747  *				/ opaque / stale / algorithm
12182882Svi117747  *				/ qop-options / auth-param
12192882Svi117747  * realm               =  "realm" EQUAL realm-value
12202882Svi117747  * realm-value         =  quoted-string
12212882Svi117747  * domain              =  "domain" EQUAL LDQUOT URI
12222882Svi117747  *				*( 1*SP URI ) RDQUOT
12232882Svi117747  * URI                 =  absoluteURI / abs-path
12242882Svi117747  * nonce               =  "nonce" EQUAL nonce-value
12252882Svi117747  * nonce-value         =  quoted-string
12262882Svi117747  * opaque              =  "opaque" EQUAL quoted-string
12272882Svi117747  * stale               =  "stale" EQUAL ( "true" / "false" )
12282882Svi117747  * algorithm           =  "algorithm" EQUAL ( "MD5" / "MD5-sess"
12292882Svi117747  *			/ token )
12302882Svi117747  * qop-options         =  "qop" EQUAL LDQUOT qop-value
12312882Svi117747  *			*("," qop-value) RDQUOT
12322882Svi117747  * qop-value           =  "auth" / "auth-int" / token
12332882Svi117747  */
12342882Svi117747 int
sip_add_proxy_authen(sip_msg_t sip_msg,char * pascheme,char * paparam)12352882Svi117747 sip_add_proxy_authen(sip_msg_t sip_msg, char *pascheme, char *paparam)
12362882Svi117747 {
12372882Svi117747 	return (sip_add_str_to_msg(sip_msg, SIP_PROXY_AUTHEN, pascheme, paparam,
12382882Svi117747 	    SIP_SP));
12392882Svi117747 }
12402882Svi117747 
12412882Svi117747 /*
12422882Svi117747  * Proxy-Authorization  =  "Proxy-Authorization" HCOLON credentials
12432882Svi117747  */
12442882Svi117747 int
sip_add_proxy_author(sip_msg_t sip_msg,char * paschem,char * paparam)12452882Svi117747 sip_add_proxy_author(sip_msg_t sip_msg, char *paschem, char *paparam)
12462882Svi117747 {
12472882Svi117747 	return (sip_add_str_to_msg(sip_msg, SIP_PROXY_AUTHOR, paschem, paparam,
12482882Svi117747 	    SIP_SP));
12492882Svi117747 }
12502882Svi117747 
12512882Svi117747 /*
12522882Svi117747  * Proxy-Require  =  "Proxy-Require" HCOLON option-tag
12532882Svi117747  *			*(COMMA option-tag)
12542882Svi117747  * option-tag     =  token
12552882Svi117747  */
12562882Svi117747 int
sip_add_proxy_require(sip_msg_t sip_msg,char * opt)12572882Svi117747 sip_add_proxy_require(sip_msg_t sip_msg, char *opt)
12582882Svi117747 {
12592882Svi117747 	return (sip_add_str_to_msg(sip_msg, SIP_PROXY_REQ, opt, NULL,
12602882Svi117747 	    (char)NULL));
12612882Svi117747 }
12622882Svi117747 
12632882Svi117747 /*
12642882Svi117747  * WWW-Authenticate  =  "WWW-Authenticate" HCOLON challenge
12652882Svi117747  * extension-header  =  header-name HCOLON header-value
12662882Svi117747  * header-name       =  token
12672882Svi117747  * header-value      =  *(TEXT-UTF8char / UTF8-CONT / LWS)
12682882Svi117747  * message-body  =  *OCTET
12692882Svi117747  */
12702882Svi117747 int
sip_add_www_authen(sip_msg_t sip_msg,char * wascheme,char * waparam)12712882Svi117747 sip_add_www_authen(sip_msg_t sip_msg, char *wascheme, char *waparam)
12722882Svi117747 {
12732882Svi117747 	return (sip_add_str_to_msg(sip_msg, SIP_WWW_AUTHEN, wascheme, waparam,
12742882Svi117747 	    SIP_SP));
12752882Svi117747 }
12762882Svi117747 
12772882Svi117747 /*
12782882Svi117747  * Call-ID  =  ( "Call-ID" / "i" ) HCOLON callid
12792882Svi117747  */
12802882Svi117747 int
sip_add_callid(sip_msg_t sip_msg,char * callid)12812882Svi117747 sip_add_callid(sip_msg_t sip_msg, char *callid)
12822882Svi117747 {
12832882Svi117747 	int		ret;
12842882Svi117747 	boolean_t	allocd = B_FALSE;
12852882Svi117747 
12862882Svi117747 	if (sip_msg == NULL || (callid != NULL && callid[0] == '\0'))
12872882Svi117747 		return (EINVAL);
12882882Svi117747 	if (callid == NULL) {
12892882Svi117747 		callid = (char *)sip_guid();
12902882Svi117747 		if (callid == NULL)
12912882Svi117747 			return (ENOMEM);
12922882Svi117747 		allocd = B_TRUE;
12932882Svi117747 	}
12942882Svi117747 	ret = sip_add_str_to_msg(sip_msg, SIP_CALL_ID, callid, NULL,
12952882Svi117747 	    (char)NULL);
12962882Svi117747 	if (allocd)
12972882Svi117747 		free(callid);
12982882Svi117747 	return (ret);
12992882Svi117747 }
13002882Svi117747 
13012882Svi117747 /*
13022882Svi117747  * CSeq  =  "CSeq" HCOLON 1*DIGIT LWS Method
13032882Svi117747  */
13042882Svi117747 int
sip_add_cseq(sip_msg_t sip_msg,sip_method_t method,uint32_t cseq)13052882Svi117747 sip_add_cseq(sip_msg_t sip_msg, sip_method_t method, uint32_t cseq)
13062882Svi117747 {
13072882Svi117747 	int	r;
13082882Svi117747 
13092882Svi117747 	if (sip_msg == NULL || (int)cseq < 0 || method == 0 ||
13102882Svi117747 	    method >= MAX_SIP_METHODS) {
13112882Svi117747 		return (EINVAL);
13122882Svi117747 	}
13132882Svi117747 	r = sip_add_intstr_to_msg(sip_msg, SIP_CSEQ, cseq,
13142882Svi117747 	    sip_methods[method].name, NULL);
13152882Svi117747 	return (r);
13162882Svi117747 }
13172882Svi117747 
13182882Svi117747 /*
13192882Svi117747  * Via =  ( "Via" / "v" ) HCOLON via-parm *(COMMA via-parm)
13202882Svi117747  * via-parm          =  sent-protocol LWS sent-by *( SEMI via-params )
13212882Svi117747  * via-params        =  via-ttl / via-maddr
13222882Svi117747  *                      / via-received / via-branch
13232882Svi117747  *                      / via-extension
13242882Svi117747  * via-ttl           =  "ttl" EQUAL ttl
13252882Svi117747  * via-maddr         =  "maddr" EQUAL host
13262882Svi117747  * via-received      =  "received" EQUAL (IPv4address / IPv6address)
13272882Svi117747  * via-branch        =  "branch" EQUAL token
13282882Svi117747  * via-extension     =  generic-param
13292882Svi117747  * sent-protocol     =  protocol-name SLASH protocol-version
13302882Svi117747  *                      SLASH transport
13312882Svi117747  * protocol-name     =  "SIP" / token
13322882Svi117747  * protocol-version  =  token
13332882Svi117747  * transport         =  "UDP" / "TCP" / "TLS" / "SCTP"
13342882Svi117747  *                      / other-transport
13352882Svi117747  * sent-by           =  host [ COLON port ]
13362882Svi117747  * ttl               =  1*3DIGIT ; 0 to 255
13372882Svi117747  */
13382882Svi117747 _sip_header_t *
sip_create_via_hdr(char * sent_protocol_transport,char * sent_by_host,int sent_by_port,char * via_params)13392882Svi117747 sip_create_via_hdr(char *sent_protocol_transport, char *sent_by_host,
13402882Svi117747     int sent_by_port, char *via_params)
13412882Svi117747 {
13422882Svi117747 	_sip_header_t	*new_header;
13432882Svi117747 	int		header_size;
13442882Svi117747 	int		count;
13452882Svi117747 
13462882Svi117747 	header_size = strlen(SIP_VIA) + SIP_SPACE_LEN + sizeof (char) +
13472882Svi117747 	    SIP_SPACE_LEN + strlen(SIP_VERSION) + sizeof (char) +
13482882Svi117747 	    strlen(sent_protocol_transport) + SIP_SPACE_LEN +
13492882Svi117747 	    strlen(sent_by_host) + strlen(SIP_CRLF);
13502882Svi117747 
13512882Svi117747 	if (sent_by_port > 0) {
13522882Svi117747 		header_size += SIP_SPACE_LEN + sizeof (char) + SIP_SPACE_LEN +
13532882Svi117747 		    sip_num_of_digits(sent_by_port);
13542882Svi117747 	}
13552882Svi117747 
13562882Svi117747 	if (via_params != NULL) {
13572882Svi117747 		header_size += SIP_SPACE_LEN + sizeof (char) +
13582882Svi117747 		    strlen(via_params);
13592882Svi117747 	}
13602882Svi117747 	new_header = sip_new_header(header_size);
13612882Svi117747 	if (new_header->sip_hdr_start == NULL)
13622882Svi117747 		return (NULL);
13632882Svi117747 	count = snprintf(new_header->sip_hdr_current, header_size + 1,
13642882Svi117747 	    "%s %c %s/%s %s",
13652882Svi117747 	    SIP_VIA, SIP_HCOLON, SIP_VERSION, sent_protocol_transport,
13662882Svi117747 	    sent_by_host);
13672882Svi117747 	new_header->sip_hdr_current += count;
13682882Svi117747 	header_size -= count;
13692882Svi117747 
13702882Svi117747 	if (sent_by_port > 0) {
13712882Svi117747 		count = snprintf(new_header->sip_hdr_current, header_size + 1,
13722882Svi117747 		    " %c %d", SIP_HCOLON, sent_by_port);
13732882Svi117747 		new_header->sip_hdr_current += count;
13742882Svi117747 		header_size -= count;
13752882Svi117747 	}
13762882Svi117747 
13772882Svi117747 	if (via_params != NULL) {
13782882Svi117747 		count = snprintf(new_header->sip_hdr_current, header_size + 1,
13792882Svi117747 		    " %c%s", SIP_SEMI, via_params);
13802882Svi117747 		new_header->sip_hdr_current += count;
13812882Svi117747 		header_size -= count;
13822882Svi117747 	}
13832882Svi117747 
13842882Svi117747 	(void) snprintf(new_header->sip_hdr_current, header_size + 1,
13852882Svi117747 	    "%s", SIP_CRLF);
13862882Svi117747 	return (new_header);
13872882Svi117747 }
13882882Svi117747 
13892882Svi117747 /*
13902882Svi117747  * There can be multiple via headers we always append the header.
13912882Svi117747  * We expect the via params to be a semi-colon separated list of parameters.
13922882Svi117747  * We will add a semi-clone, before adding the list to the header.
13932882Svi117747  */
13942882Svi117747 int
sip_add_via(sip_msg_t sip_msg,char * sent_protocol_transport,char * sent_by_host,int sent_by_port,char * via_params)13952882Svi117747 sip_add_via(sip_msg_t sip_msg, char *sent_protocol_transport,
13962882Svi117747     char *sent_by_host, int sent_by_port, char *via_params)
13972882Svi117747 {
13982882Svi117747 	_sip_header_t	*new_header;
13992882Svi117747 	_sip_msg_t	*_sip_msg;
14002882Svi117747 
14012882Svi117747 	if (sip_msg == NULL || sent_protocol_transport == NULL ||
14022882Svi117747 	    sent_by_host == NULL || sent_by_port < 0) {
14032882Svi117747 		return (EINVAL);
14042882Svi117747 	}
14052882Svi117747 
14062882Svi117747 	_sip_msg = (_sip_msg_t *)sip_msg;
14072882Svi117747 	(void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
14082882Svi117747 	if (_sip_msg->sip_msg_cannot_be_modified) {
14092882Svi117747 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
14102882Svi117747 		return (ENOTSUP);
14112882Svi117747 	}
14122882Svi117747 
14132882Svi117747 	new_header = sip_create_via_hdr(sent_protocol_transport, sent_by_host,
14142882Svi117747 	    sent_by_port, via_params);
14152882Svi117747 	if (new_header == NULL) {
14162882Svi117747 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
14172882Svi117747 		return (ENOMEM);
14182882Svi117747 	}
14192882Svi117747 	_sip_add_header(_sip_msg, new_header, B_TRUE, B_FALSE, NULL);
14202882Svi117747 	if (_sip_msg->sip_msg_buf != NULL)
14212882Svi117747 		_sip_msg->sip_msg_modified = B_TRUE;
14222882Svi117747 	(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
14232882Svi117747 	return (0);
14242882Svi117747 }
14252882Svi117747 
14262882Svi117747 /*
14272882Svi117747  * Max-Forwards  =  "Max-Forwards" HCOLON 1*DIGIT
14282882Svi117747  */
14292882Svi117747 int
sip_add_maxforward(sip_msg_t sip_msg,uint_t maxforward)14302882Svi117747 sip_add_maxforward(sip_msg_t sip_msg, uint_t maxforward)
14312882Svi117747 {
14322882Svi117747 	if (sip_msg == NULL || (int)maxforward < 0)
14332882Svi117747 		return (EINVAL);
14342882Svi117747 	return (sip_add_int_to_msg(sip_msg, SIP_MAX_FORWARDS, maxforward,
14352882Svi117747 	    NULL));
14362882Svi117747 }
14372882Svi117747 
14382882Svi117747 /*
14392882Svi117747  * Content-Type     =  ( "Content-Type" / "c" ) HCOLON media-type
14402882Svi117747  * media-type       =  m-type SLASH m-subtype *(SEMI m-parameter)
14412882Svi117747  * m-type           =  discrete-type / composite-type
14422882Svi117747  * discrete-type    =  "text" / "image" / "audio" / "video"
14432882Svi117747  *			/ "application" / extension-token
14442882Svi117747  * composite-type   =  "message" / "multipart" / extension-token
14452882Svi117747  * extension-token  =  ietf-token / x-token
14462882Svi117747  * ietf-token       =  token
14472882Svi117747  * x-token          =  "x-" token
14482882Svi117747  * m-subtype        =  extension-token / iana-token
14492882Svi117747  * iana-token       =  token
14502882Svi117747  * m-parameter      =  m-attribute EQUAL m-value
14512882Svi117747  * m-attribute      =  token
14522882Svi117747  * m-value          =  token / quoted-string
14532882Svi117747  */
14542882Svi117747 int
sip_add_content_type(sip_msg_t sip_msg,char * type,char * subtype)14552882Svi117747 sip_add_content_type(sip_msg_t sip_msg, char *type, char *subtype)
14562882Svi117747 {
14572882Svi117747 	if (sip_msg == NULL || type == NULL || subtype == NULL)
14582882Svi117747 		return (EINVAL);
14592882Svi117747 	return (sip_add_2strs_to_msg(sip_msg, SIP_CONTENT_TYPE, type, B_FALSE,
14602882Svi117747 	    subtype, NULL, SIP_SLASH));
14612882Svi117747 }
14622882Svi117747 
14632882Svi117747 /*
14642882Svi117747  * Content-Length  =  ( "Content-Length" / "l" ) HCOLON 1*DIGIT
14652882Svi117747  */
14662882Svi117747 int
sip_add_content_length(_sip_msg_t * _sip_msg,int length)14672882Svi117747 sip_add_content_length(_sip_msg_t *_sip_msg, int length)
14682882Svi117747 {
14692882Svi117747 	_sip_header_t	*new_header;
14702882Svi117747 	int 		header_size;
14712882Svi117747 
14722882Svi117747 	if (_sip_msg == NULL || length < 0)
14732882Svi117747 		return (EINVAL);
14742882Svi117747 	(void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
14752882Svi117747 	if (_sip_msg->sip_msg_cannot_be_modified) {
14762882Svi117747 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
14772882Svi117747 		return (ENOTSUP);
14782882Svi117747 	}
14792882Svi117747 
14802882Svi117747 	header_size = strlen(SIP_CONTENT_LENGTH) + SIP_SPACE_LEN +
14812882Svi117747 	    sizeof (char) + SIP_SPACE_LEN + sip_num_of_digits(length) +
14822882Svi117747 	    strlen(SIP_CRLF) + strlen(SIP_CRLF);
14832882Svi117747 
14842882Svi117747 	new_header = sip_new_header(header_size);
14852882Svi117747 	if (new_header == NULL) {
14862882Svi117747 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
14872882Svi117747 		return (ENOMEM);
14882882Svi117747 	}
14892882Svi117747 	(void) snprintf(new_header->sip_hdr_start, header_size + 1,
14902882Svi117747 	    "%s %c %u%s%s", SIP_CONTENT_LENGTH, SIP_HCOLON, length,
14912882Svi117747 	    SIP_CRLF, SIP_CRLF);
14922882Svi117747 
14932882Svi117747 	_sip_add_header(_sip_msg, new_header, B_TRUE, B_FALSE, NULL);
14942882Svi117747 	if (_sip_msg->sip_msg_buf != NULL)
14952882Svi117747 		_sip_msg->sip_msg_modified = B_TRUE;
14962882Svi117747 	(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
14972882Svi117747 	return (0);
14982882Svi117747 }
14992882Svi117747 
15002882Svi117747 
15012882Svi117747 /*
15022882Svi117747  * Contact = ("Contact" / "m" ) HCOLON
15032882Svi117747  *		( STAR / (contact-param *(COMMA contact-param)))
15042882Svi117747  * contact-param  =  (name-addr / addr-spec) *(SEMI contact-params)
15052882Svi117747  * name-addr      =  [ display-name ] LAQUOT addr-spec RAQUOT
15062882Svi117747  * addr-spec      =  SIP-URI / SIPS-URI / absoluteURI
15072882Svi117747  * display-name   =  *(token LWS)/ quoted-string
15082882Svi117747  * contact-params     =  c-p-q / c-p-expires
15092882Svi117747  *                     / contact-extension
15102882Svi117747  */
15112882Svi117747 int
sip_add_contact(sip_msg_t sip_msg,char * display_name,char * contact_uri,boolean_t add_aquot,char * contact_params)15122882Svi117747 sip_add_contact(sip_msg_t sip_msg, char *display_name, char *contact_uri,
15132882Svi117747     boolean_t add_aquot, char *contact_params)
15142882Svi117747 {
15152882Svi117747 	return (sip_add_name_aspec(sip_msg, display_name, contact_uri, NULL,
15162882Svi117747 	    add_aquot, SIP_CONTACT, contact_params));
15172882Svi117747 }
15182882Svi117747 
15192882Svi117747 /*
15202882Svi117747  * From =  ( "From" / "f" ) HCOLON from-spec
15212882Svi117747  * from-spec = ( name-addr / addr-spec )
15222882Svi117747  *	*( SEMI from-param )
15232882Svi117747  * from-param  =  tag-param / generic-param
15242882Svi117747  * tag-param   =  "tag" EQUAL token
15252882Svi117747  *
15262882Svi117747  * Since there can be more than one tags, fromtags is a semi colon separated
15272882Svi117747  * list of tags.
15282882Svi117747  */
15292882Svi117747 int
sip_add_from(sip_msg_t sip_msg,char * display_name,char * from_uri,char * fromtags,boolean_t add_aquot,char * from_params)15302882Svi117747 sip_add_from(sip_msg_t sip_msg, char *display_name, char *from_uri,
15312882Svi117747     char *fromtags, boolean_t add_aquot, char *from_params)
15322882Svi117747 {
15332882Svi117747 	return (sip_add_name_aspec(sip_msg, display_name, from_uri, fromtags,
15342882Svi117747 	    add_aquot, SIP_FROM, from_params));
15352882Svi117747 }
15362882Svi117747 
15372882Svi117747 /*
15382882Svi117747  * To =  ( "To" / "t" ) HCOLON ( name-addr
15392882Svi117747  *	/ addr-spec ) *( SEMI to-param )
15402882Svi117747  * to-param  =  tag-param / generic-param
15412882Svi117747  */
15422882Svi117747 int
sip_add_to(sip_msg_t sip_msg,char * display_name,char * to_uri,char * totags,boolean_t add_aquot,char * to_params)15432882Svi117747 sip_add_to(sip_msg_t sip_msg, char *display_name, char *to_uri,
15442882Svi117747     char *totags, boolean_t add_aquot, char *to_params)
15452882Svi117747 {
15462882Svi117747 	return (sip_add_name_aspec(sip_msg, display_name, to_uri, totags,
15472882Svi117747 	    add_aquot, SIP_TO, to_params));
15482882Svi117747 }
15492882Svi117747 
15502882Svi117747 /*
15512882Svi117747  * Route        =  "Route" HCOLON route-param *(COMMA route-param)
15522882Svi117747  * route-param  =  name-addr *( SEMI rr-param )
15532882Svi117747  */
15542882Svi117747 int
sip_add_route(sip_msg_t sip_msg,char * display_name,char * uri,char * route_params)15552882Svi117747 sip_add_route(sip_msg_t sip_msg, char *display_name, char *uri,
15562882Svi117747     char *route_params)
15572882Svi117747 {
15582882Svi117747 	return (sip_add_name_aspec(sip_msg, display_name, uri, NULL, B_TRUE,
15592882Svi117747 	    SIP_ROUTE, route_params));
15602882Svi117747 }
15612882Svi117747 
15622882Svi117747 /*
15632882Svi117747  * Record-Route  =  "Record-Route" HCOLON rec-route *(COMMA rec-route)
15642882Svi117747  * rec-route     =  name-addr *( SEMI rr-param )
15652882Svi117747  * rr-param      =  generic-param
15662882Svi117747  */
15672882Svi117747 int
sip_add_record_route(sip_msg_t sip_msg,char * display_name,char * uri,char * route_params)15682882Svi117747 sip_add_record_route(sip_msg_t sip_msg, char *display_name, char *uri,
15692882Svi117747     char *route_params)
15702882Svi117747 {
15712882Svi117747 	return (sip_add_name_aspec(sip_msg, display_name, uri, NULL, B_TRUE,
15722882Svi117747 	    SIP_RECORD_ROUTE, route_params));
15732882Svi117747 }
15742882Svi117747 
15752882Svi117747 
15762882Svi117747 /*
15772882Svi117747  * PAssertedID = "P-Asserted-Identity" HCOLON PAssertedID-value
15782882Svi117747  *			*(COMMA PAssertedID-value)
15792882Svi117747  * PAssertedID-value = name-addr / addr-spec
15802882Svi117747  */
15812882Svi117747 int
sip_add_passertedid(sip_msg_t sip_msg,char * display_name,char * addr,boolean_t add_aquot)15822882Svi117747 sip_add_passertedid(sip_msg_t sip_msg, char *display_name, char *addr,
15832882Svi117747     boolean_t add_aquot)
15842882Svi117747 {
15852882Svi117747 	return (sip_add_name_aspec(sip_msg, display_name, addr, NULL, add_aquot,
15862882Svi117747 	    SIP_PASSERTEDID, NULL));
15872882Svi117747 }
15882882Svi117747 
15892882Svi117747 /*
15902882Svi117747  * PPreferredID = "P-Preferred-Identity" HCOLON PPreferredID-value
15912882Svi117747  *			*(COMMA PPreferredID-value)
15922882Svi117747  * PPreferredID-value = name-addr / addr-spec
15932882Svi117747  */
15942882Svi117747 int
sip_add_ppreferredid(sip_msg_t sip_msg,char * display_name,char * addr,boolean_t add_aquot)15952882Svi117747 sip_add_ppreferredid(sip_msg_t sip_msg, char *display_name, char *addr,
15962882Svi117747     boolean_t add_aquot)
15972882Svi117747 {
15982882Svi117747 	return (sip_add_name_aspec(sip_msg, display_name, addr, NULL, add_aquot,
15992882Svi117747 	    SIP_PPREFERREDID, NULL));
16002882Svi117747 }
1601