140cb5e5dSvi /*
240cb5e5dSvi  * CDDL HEADER START
340cb5e5dSvi  *
440cb5e5dSvi  * The contents of this file are subject to the terms of the
540cb5e5dSvi  * Common Development and Distribution License (the "License").
640cb5e5dSvi  * You may not use this file except in compliance with the License.
740cb5e5dSvi  *
840cb5e5dSvi  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
940cb5e5dSvi  * or http://www.opensolaris.org/os/licensing.
1040cb5e5dSvi  * See the License for the specific language governing permissions
1140cb5e5dSvi  * and limitations under the License.
1240cb5e5dSvi  *
1340cb5e5dSvi  * When distributing Covered Code, include this CDDL HEADER in each
1440cb5e5dSvi  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1540cb5e5dSvi  * If applicable, add the following below this CDDL HEADER, with the
1640cb5e5dSvi  * fields enclosed by brackets "[]" replaced with your own identifying
1740cb5e5dSvi  * information: Portions Copyright [yyyy] [name of copyright owner]
1840cb5e5dSvi  *
1940cb5e5dSvi  * CDDL HEADER END
2040cb5e5dSvi  */
2140cb5e5dSvi 
2240cb5e5dSvi /*
232c2c4183Svi  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
2440cb5e5dSvi  * Use is subject to license terms.
2540cb5e5dSvi  */
2640cb5e5dSvi 
272c2c4183Svi #include <stdio.h>
282c2c4183Svi #include <ctype.h>
292c2c4183Svi #include <errno.h>
302c2c4183Svi #include <pthread.h>
312c2c4183Svi #include <strings.h>
322c2c4183Svi #include <stdlib.h>
332c2c4183Svi #include <sip.h>
342c2c4183Svi 
3540cb5e5dSvi #include "sip_msg.h"
3640cb5e5dSvi #include "sip_miscdefs.h"
3740cb5e5dSvi 
3840cb5e5dSvi /*
3940cb5e5dSvi  * Returns number of digits in the given int
4040cb5e5dSvi  */
4140cb5e5dSvi static int
sip_num_of_digits(int num)4240cb5e5dSvi sip_num_of_digits(int num)
4340cb5e5dSvi {
4440cb5e5dSvi 	int	num_of_bytes = 0;
4540cb5e5dSvi 
4640cb5e5dSvi 	do {
4740cb5e5dSvi 		num_of_bytes += 1;
4840cb5e5dSvi 		num = num / 10;
4940cb5e5dSvi 	} while (num > 0);
5040cb5e5dSvi 	return (num_of_bytes);
5140cb5e5dSvi }
5240cb5e5dSvi 
5340cb5e5dSvi /*
5440cb5e5dSvi  * Return the int as a string
5540cb5e5dSvi  */
5640cb5e5dSvi static char *
sip_int_to_str(int i)5740cb5e5dSvi sip_int_to_str(int i)
5840cb5e5dSvi {
5940cb5e5dSvi 	int	count;
6040cb5e5dSvi 	int	t;
6140cb5e5dSvi 	int	x;
6240cb5e5dSvi 	char	*str;
6340cb5e5dSvi 
6440cb5e5dSvi 	if (i < 0)
6540cb5e5dSvi 		return (NULL);
6640cb5e5dSvi 	/*
6740cb5e5dSvi 	 * the following two loops convert int i to str
6840cb5e5dSvi 	 */
6940cb5e5dSvi 	count = 1;
7040cb5e5dSvi 	t = i;
7140cb5e5dSvi 	while ((t = t / 10) != 0) {
7240cb5e5dSvi 		count++;
7340cb5e5dSvi 	}
7440cb5e5dSvi 
7540cb5e5dSvi 	str = calloc(1, sizeof (char) * count + 1);
7640cb5e5dSvi 	if (str == NULL)
7740cb5e5dSvi 		return (NULL);
7840cb5e5dSvi 	t = i;
7940cb5e5dSvi 	for (x = 0; x < count; x++) {
8040cb5e5dSvi 		int a;
8140cb5e5dSvi 		a = t % 10;
8240cb5e5dSvi 		str[count - 1 - x] = a + '0';
8340cb5e5dSvi 		t = t / 10;
8440cb5e5dSvi 	}
8540cb5e5dSvi 	str[count] = '\0';
8640cb5e5dSvi 	return (str);
8740cb5e5dSvi }
8840cb5e5dSvi 
8940cb5e5dSvi /*
9040cb5e5dSvi  * Add quotes to the give str and return the quoted string
9140cb5e5dSvi  */
9240cb5e5dSvi static char *
sip_add_aquot_to_str(char * str,boolean_t * alloc)9340cb5e5dSvi sip_add_aquot_to_str(char *str, boolean_t *alloc)
9440cb5e5dSvi {
95*559f8b54SToomas Soome 	char		*new_str;
96*559f8b54SToomas Soome 	char		*tmp = str;
9740cb5e5dSvi 	int		size;
9840cb5e5dSvi 
9940cb5e5dSvi 	while (isspace(*tmp))
10040cb5e5dSvi 		tmp++;
10140cb5e5dSvi 
10240cb5e5dSvi 	*alloc = B_FALSE;
10340cb5e5dSvi 	if (*tmp != SIP_LAQUOT) {
10440cb5e5dSvi 		size = strlen(str) + 2 * sizeof (char);
10540cb5e5dSvi 		new_str = calloc(1, size + 1);
10640cb5e5dSvi 		if (new_str == NULL)
10740cb5e5dSvi 			return (NULL);
10840cb5e5dSvi 		new_str[0] = SIP_LAQUOT;
10940cb5e5dSvi 		new_str[1] = '\0';
11040cb5e5dSvi 		(void) strncat(new_str, str, strlen(str));
11140cb5e5dSvi 		(void) strncat(new_str, ">", 1);
11240cb5e5dSvi 		new_str[size] = '\0';
11340cb5e5dSvi 		*alloc = B_TRUE;
11440cb5e5dSvi 		return (new_str);
11540cb5e5dSvi 	}
11640cb5e5dSvi 
11740cb5e5dSvi 	return (str);
11840cb5e5dSvi }
11940cb5e5dSvi 
12040cb5e5dSvi /*
12140cb5e5dSvi  * Add an empty header
12240cb5e5dSvi  */
12340cb5e5dSvi static int
sip_add_empty_hdr(sip_msg_t sip_msg,char * hdr_name)12440cb5e5dSvi sip_add_empty_hdr(sip_msg_t sip_msg, char *hdr_name)
12540cb5e5dSvi {
12640cb5e5dSvi 	_sip_header_t	*new_header;
127*559f8b54SToomas Soome 	int		header_size;
128*559f8b54SToomas Soome 	_sip_msg_t	*_sip_msg;
12940cb5e5dSvi 	int		csize = sizeof (char);
13040cb5e5dSvi 
13140cb5e5dSvi 	if (sip_msg == NULL || hdr_name == NULL)
13240cb5e5dSvi 		return (EINVAL);
13340cb5e5dSvi 	_sip_msg = (_sip_msg_t *)sip_msg;
13440cb5e5dSvi 	(void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
13540cb5e5dSvi 	if (_sip_msg->sip_msg_cannot_be_modified) {
13640cb5e5dSvi 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
13740cb5e5dSvi 		return (ENOTSUP);
13840cb5e5dSvi 	}
13940cb5e5dSvi 
14040cb5e5dSvi 	header_size = strlen(hdr_name) + SIP_SPACE_LEN + csize;
14140cb5e5dSvi 
14240cb5e5dSvi 	new_header = sip_new_header(header_size);
14340cb5e5dSvi 	if (new_header == NULL) {
14440cb5e5dSvi 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
14540cb5e5dSvi 		return (ENOMEM);
14640cb5e5dSvi 	}
14740cb5e5dSvi 
14840cb5e5dSvi 	(void) snprintf(new_header->sip_hdr_start, header_size + 1,
14940cb5e5dSvi 	    "%s %c",  hdr_name, SIP_HCOLON);
15040cb5e5dSvi 
15140cb5e5dSvi 	_sip_add_header(_sip_msg, new_header, B_TRUE, B_FALSE, hdr_name);
15240cb5e5dSvi 	if (_sip_msg->sip_msg_buf != NULL)
15340cb5e5dSvi 		_sip_msg->sip_msg_modified = B_TRUE;
15440cb5e5dSvi 	(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
15540cb5e5dSvi 
15640cb5e5dSvi 	return (0);
15740cb5e5dSvi }
15840cb5e5dSvi 
15940cb5e5dSvi /*
16040cb5e5dSvi  * Generic function to add a header with two strings to message
16140cb5e5dSvi  */
16240cb5e5dSvi 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)16340cb5e5dSvi sip_add_2strs_to_msg(sip_msg_t sip_msg, char *hdr_name, char *str1,
16440cb5e5dSvi     boolean_t qstr1, char *str2, char *plist, char sep)
16540cb5e5dSvi {
16640cb5e5dSvi 	_sip_header_t	*new_header;
167*559f8b54SToomas Soome 	int		header_size;
168*559f8b54SToomas Soome 	_sip_msg_t	*_sip_msg;
16940cb5e5dSvi 	int		csize = sizeof (char);
17040cb5e5dSvi 
17140cb5e5dSvi 	if (sip_msg == NULL || str1 == NULL || str2 == NULL ||
17240cb5e5dSvi 	    (str1 != NULL && str1[0] == '\0') ||
17340cb5e5dSvi 	    (str2 != NULL && str2[0] == '\0')) {
17440cb5e5dSvi 		return (EINVAL);
17540cb5e5dSvi 	}
17640cb5e5dSvi 	_sip_msg = (_sip_msg_t *)sip_msg;
17740cb5e5dSvi 	(void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
17840cb5e5dSvi 	if (_sip_msg->sip_msg_cannot_be_modified) {
17940cb5e5dSvi 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
18040cb5e5dSvi 		return (ENOTSUP);
18140cb5e5dSvi 	}
18240cb5e5dSvi 
18340cb5e5dSvi 	if (plist == NULL) {
18440cb5e5dSvi 		header_size = strlen(hdr_name) + SIP_SPACE_LEN + csize +
18540cb5e5dSvi 		    SIP_SPACE_LEN + strlen(str1) + csize + strlen(str2) +
18640cb5e5dSvi 		    strlen(SIP_CRLF);
18740cb5e5dSvi 	} else {
18840cb5e5dSvi 		header_size = strlen(hdr_name) + SIP_SPACE_LEN + csize +
18940cb5e5dSvi 		    SIP_SPACE_LEN + strlen(str1) + csize + strlen(str2) +
19040cb5e5dSvi 		    csize + strlen(plist) + strlen(SIP_CRLF);
19140cb5e5dSvi 	}
19240cb5e5dSvi 	if (qstr1)
19340cb5e5dSvi 		header_size += 2 * sizeof (char);
19440cb5e5dSvi 
19540cb5e5dSvi 	new_header = sip_new_header(header_size);
19640cb5e5dSvi 	if (new_header == NULL) {
19740cb5e5dSvi 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
19840cb5e5dSvi 		return (ENOMEM);
19940cb5e5dSvi 	}
20040cb5e5dSvi 
20140cb5e5dSvi 	if (plist == NULL) {
20240cb5e5dSvi 		if (qstr1) {
20340cb5e5dSvi 			(void) snprintf(new_header->sip_hdr_start,
20440cb5e5dSvi 			    header_size + 1, "%s %c \"%s\"%c%s%s",
20540cb5e5dSvi 			    hdr_name, SIP_HCOLON, str1, sep, str2, SIP_CRLF);
20640cb5e5dSvi 		} else {
20740cb5e5dSvi 			(void) snprintf(new_header->sip_hdr_start,
20840cb5e5dSvi 			    header_size + 1, "%s %c %s%c%s%s",
20940cb5e5dSvi 			    hdr_name, SIP_HCOLON, str1, sep, str2, SIP_CRLF);
21040cb5e5dSvi 		}
21140cb5e5dSvi 	} else {
21240cb5e5dSvi 		if (qstr1) {
21340cb5e5dSvi 			(void) snprintf(new_header->sip_hdr_start,
21440cb5e5dSvi 			    header_size + 1,
21540cb5e5dSvi 			    "%s %c \"%s\"%c%s%c%s%s", hdr_name, SIP_HCOLON,
21640cb5e5dSvi 			    str1, sep, str2, SIP_SEMI, plist, SIP_CRLF);
21740cb5e5dSvi 		} else {
21840cb5e5dSvi 			(void) snprintf(new_header->sip_hdr_start,
21940cb5e5dSvi 			    header_size + 1, "%s %c %s%c%s%c%s%s",
22040cb5e5dSvi 			    hdr_name, SIP_HCOLON, str1, sep, str2, SIP_SEMI,
22140cb5e5dSvi 			    plist, SIP_CRLF);
22240cb5e5dSvi 		}
22340cb5e5dSvi 	}
22440cb5e5dSvi 	_sip_add_header(_sip_msg, new_header, B_TRUE, B_FALSE, NULL);
22540cb5e5dSvi 	if (_sip_msg->sip_msg_buf != NULL)
22640cb5e5dSvi 		_sip_msg->sip_msg_modified = B_TRUE;
22740cb5e5dSvi 	(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
22840cb5e5dSvi 
22940cb5e5dSvi 	return (0);
23040cb5e5dSvi }
23140cb5e5dSvi 
23240cb5e5dSvi /*
23340cb5e5dSvi  * Generic function to add a header with a string to message
23440cb5e5dSvi  */
23540cb5e5dSvi static int
sip_add_str_to_msg(sip_msg_t sip_msg,char * hdr_name,char * str,char * plist,char param_sep)23640cb5e5dSvi sip_add_str_to_msg(sip_msg_t sip_msg, char *hdr_name, char *str, char *plist,
23740cb5e5dSvi     char param_sep)
23840cb5e5dSvi {
23940cb5e5dSvi 	_sip_header_t	*new_header;
240*559f8b54SToomas Soome 	int		header_size;
241*559f8b54SToomas Soome 	_sip_msg_t	*_sip_msg;
24240cb5e5dSvi 	int		csize = sizeof (char);
24340cb5e5dSvi 
24440cb5e5dSvi 	if (sip_msg == NULL || str == NULL || (str != NULL && str[0] == '\0'))
24540cb5e5dSvi 		return (EINVAL);
24640cb5e5dSvi 	_sip_msg = (_sip_msg_t *)sip_msg;
24740cb5e5dSvi 	(void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
24840cb5e5dSvi 	if (_sip_msg->sip_msg_cannot_be_modified) {
24940cb5e5dSvi 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
25040cb5e5dSvi 		return (ENOTSUP);
25140cb5e5dSvi 	}
25240cb5e5dSvi 
25340cb5e5dSvi 	if (plist == NULL) {
25440cb5e5dSvi 		header_size = strlen(hdr_name) + SIP_SPACE_LEN + csize +
25540cb5e5dSvi 		    SIP_SPACE_LEN + + strlen(str) + strlen(SIP_CRLF);
25640cb5e5dSvi 	} else {
25740cb5e5dSvi 		header_size = strlen(hdr_name) + SIP_SPACE_LEN + csize +
25840cb5e5dSvi 		    SIP_SPACE_LEN + + strlen(str) + csize + strlen(plist) +
25940cb5e5dSvi 		    strlen(SIP_CRLF);
26040cb5e5dSvi 	}
26140cb5e5dSvi 
26240cb5e5dSvi 	new_header = sip_new_header(header_size);
26340cb5e5dSvi 	if (new_header == NULL) {
26440cb5e5dSvi 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
26540cb5e5dSvi 		return (ENOMEM);
26640cb5e5dSvi 	}
26740cb5e5dSvi 	if (plist == NULL) {
26840cb5e5dSvi 		(void) snprintf(new_header->sip_hdr_start, header_size + 1,
26940cb5e5dSvi 		    "%s %c %s%s", hdr_name, SIP_HCOLON, str, SIP_CRLF);
27040cb5e5dSvi 	} else {
27140cb5e5dSvi 		(void) snprintf(new_header->sip_hdr_start, header_size + 1,
27240cb5e5dSvi 		    "%s %c %s%c%s%s", hdr_name, SIP_HCOLON, str, param_sep,
27340cb5e5dSvi 		    plist, SIP_CRLF);
27440cb5e5dSvi 	}
27540cb5e5dSvi 	_sip_add_header(_sip_msg, new_header, B_TRUE, B_FALSE, NULL);
27640cb5e5dSvi 	if (_sip_msg->sip_msg_buf != NULL)
27740cb5e5dSvi 		_sip_msg->sip_msg_modified = B_TRUE;
27840cb5e5dSvi 	(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
27940cb5e5dSvi 
28040cb5e5dSvi 	return (0);
28140cb5e5dSvi }
28240cb5e5dSvi 
28340cb5e5dSvi /*
28440cb5e5dSvi  * Add an header with an int to sip_msg
28540cb5e5dSvi  */
28640cb5e5dSvi static int
sip_add_int_to_msg(sip_msg_t sip_msg,char * hdr_name,int i,char * plist)28740cb5e5dSvi sip_add_int_to_msg(sip_msg_t sip_msg, char *hdr_name, int i, char *plist)
28840cb5e5dSvi {
28940cb5e5dSvi 	_sip_header_t	*new_header;
290*559f8b54SToomas Soome 	int		header_size;
291*559f8b54SToomas Soome 	_sip_msg_t	*_sip_msg;
29240cb5e5dSvi 	char		*digit_str;
29340cb5e5dSvi 	int		csize = sizeof (char);
29440cb5e5dSvi 
29540cb5e5dSvi 	if (sip_msg == NULL || (hdr_name == NULL))
29640cb5e5dSvi 		return (EINVAL);
29740cb5e5dSvi 	_sip_msg = (_sip_msg_t *)sip_msg;
29840cb5e5dSvi 	(void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
29940cb5e5dSvi 	if (_sip_msg->sip_msg_cannot_be_modified) {
30040cb5e5dSvi 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
30140cb5e5dSvi 		return (ENOTSUP);
30240cb5e5dSvi 	}
30340cb5e5dSvi 
30440cb5e5dSvi 	/*
30540cb5e5dSvi 	 * the following two loops convert int i to str
30640cb5e5dSvi 	 */
30740cb5e5dSvi 	digit_str = sip_int_to_str(i);
30840cb5e5dSvi 	if (digit_str == NULL)
30940cb5e5dSvi 		return (EINVAL);
31040cb5e5dSvi 
31140cb5e5dSvi 	if (plist == NULL) {
31240cb5e5dSvi 		header_size = strlen(hdr_name) + SIP_SPACE_LEN + csize +
31340cb5e5dSvi 		    SIP_SPACE_LEN + strlen(digit_str) + strlen(SIP_CRLF);
31440cb5e5dSvi 	} else {
31540cb5e5dSvi 		header_size = strlen(hdr_name) + SIP_SPACE_LEN + csize +
31640cb5e5dSvi 		    SIP_SPACE_LEN + strlen(digit_str) + csize +
31740cb5e5dSvi 		    strlen(plist) + strlen(SIP_CRLF);
31840cb5e5dSvi 	}
31940cb5e5dSvi 
32040cb5e5dSvi 	new_header = sip_new_header(header_size);
32140cb5e5dSvi 	if (new_header == NULL) {
32240cb5e5dSvi 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
32340cb5e5dSvi 		free(digit_str);
32440cb5e5dSvi 		return (ENOMEM);
32540cb5e5dSvi 	}
32640cb5e5dSvi 
32740cb5e5dSvi 	if (plist == NULL) {
32840cb5e5dSvi 		(void) snprintf(new_header->sip_hdr_start, header_size + 1,
32940cb5e5dSvi 		    "%s %c %s%s", hdr_name, SIP_HCOLON, digit_str, SIP_CRLF);
33040cb5e5dSvi 	} else {
33140cb5e5dSvi 		(void) snprintf(new_header->sip_hdr_start, header_size + 1,
33240cb5e5dSvi 		    "%s %c %s%c%s%s", hdr_name, SIP_HCOLON, digit_str,
33340cb5e5dSvi 		    SIP_SEMI, plist, SIP_CRLF);
33440cb5e5dSvi 	}
33540cb5e5dSvi 	free(digit_str);
33640cb5e5dSvi 	_sip_add_header(_sip_msg, new_header, B_TRUE, B_FALSE, NULL);
33740cb5e5dSvi 	if (_sip_msg->sip_msg_buf != NULL)
33840cb5e5dSvi 		_sip_msg->sip_msg_modified = B_TRUE;
33940cb5e5dSvi 	(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
34040cb5e5dSvi 
34140cb5e5dSvi 	return (0);
34240cb5e5dSvi }
34340cb5e5dSvi 
34440cb5e5dSvi /*
34540cb5e5dSvi  * Add a header with an int and string to sip_msg
34640cb5e5dSvi  */
34740cb5e5dSvi static int
sip_add_intstr_to_msg(sip_msg_t sip_msg,char * hdr_name,int i,char * s,char * plist)34840cb5e5dSvi sip_add_intstr_to_msg(sip_msg_t sip_msg, char *hdr_name, int i, char *s,
34940cb5e5dSvi     char *plist)
35040cb5e5dSvi {
35140cb5e5dSvi 	_sip_header_t	*new_header;
352*559f8b54SToomas Soome 	int		header_size;
353*559f8b54SToomas Soome 	_sip_msg_t	*_sip_msg;
35440cb5e5dSvi 	char		*digit_str;
35540cb5e5dSvi 	int		csize = sizeof (char);
35640cb5e5dSvi 
35740cb5e5dSvi 	if (sip_msg == NULL || (hdr_name == NULL))
35840cb5e5dSvi 		return (EINVAL);
35940cb5e5dSvi 	_sip_msg = (_sip_msg_t *)sip_msg;
36040cb5e5dSvi 	(void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
36140cb5e5dSvi 	if (_sip_msg->sip_msg_cannot_be_modified) {
36240cb5e5dSvi 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
36340cb5e5dSvi 		return (ENOTSUP);
36440cb5e5dSvi 	}
36540cb5e5dSvi 
36640cb5e5dSvi 	/*
36740cb5e5dSvi 	 * the following two loops convert int i to str
36840cb5e5dSvi 	 */
36940cb5e5dSvi 	digit_str = sip_int_to_str(i);
37040cb5e5dSvi 	if (digit_str == NULL) {
37140cb5e5dSvi 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
37240cb5e5dSvi 		return (EINVAL);
37340cb5e5dSvi 	}
37440cb5e5dSvi 	if (plist == NULL) {
37540cb5e5dSvi 		header_size = strlen(hdr_name) + SIP_SPACE_LEN + csize +
37640cb5e5dSvi 		    SIP_SPACE_LEN + strlen(digit_str) + csize + strlen(s) +
37740cb5e5dSvi 		    strlen(SIP_CRLF);
37840cb5e5dSvi 	} else {
37940cb5e5dSvi 		header_size = strlen(hdr_name) + SIP_SPACE_LEN + csize +
38040cb5e5dSvi 		    SIP_SPACE_LEN + strlen(digit_str) + csize + strlen(s) +
38140cb5e5dSvi 		    csize + strlen(plist) + strlen(SIP_CRLF);
38240cb5e5dSvi 	}
38340cb5e5dSvi 
38440cb5e5dSvi 	new_header = sip_new_header(header_size);
38540cb5e5dSvi 	if (new_header == NULL) {
38640cb5e5dSvi 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
38740cb5e5dSvi 		free(digit_str);
38840cb5e5dSvi 		return (ENOMEM);
38940cb5e5dSvi 	}
39040cb5e5dSvi 
39140cb5e5dSvi 	if (plist == NULL) {
39240cb5e5dSvi 		(void) snprintf(new_header->sip_hdr_start, header_size + 1,
39340cb5e5dSvi 		    "%s %c %s %s%s", hdr_name, SIP_HCOLON, digit_str, s,
39440cb5e5dSvi 		    SIP_CRLF);
39540cb5e5dSvi 	} else {
39640cb5e5dSvi 		(void) snprintf(new_header->sip_hdr_start, header_size + 1,
39740cb5e5dSvi 		    "%s %c %s %s%c%s%s", hdr_name, SIP_HCOLON, digit_str,
39840cb5e5dSvi 		    s, SIP_SEMI, plist, SIP_CRLF);
39940cb5e5dSvi 	}
40040cb5e5dSvi 	free(digit_str);
40140cb5e5dSvi 	_sip_add_header(_sip_msg, new_header, B_TRUE, B_FALSE, NULL);
40240cb5e5dSvi 	if (_sip_msg->sip_msg_buf != NULL)
40340cb5e5dSvi 		_sip_msg->sip_msg_modified = B_TRUE;
40440cb5e5dSvi 	(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
40540cb5e5dSvi 
40640cb5e5dSvi 	return (0);
40740cb5e5dSvi }
40840cb5e5dSvi 
40940cb5e5dSvi /*
41040cb5e5dSvi  * Generic function to add Contact, From,  To, Route or Record-Route header
41140cb5e5dSvi  */
41240cb5e5dSvi 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)41340cb5e5dSvi sip_add_name_aspec(sip_msg_t sip_msg, char *display_name, char *uri,
41440cb5e5dSvi     char *tags, boolean_t add_aquot, char *header_name, char *params)
41540cb5e5dSvi {
41640cb5e5dSvi 	char		*t = uri;
41740cb5e5dSvi 	boolean_t	qalloc = B_FALSE;
41840cb5e5dSvi 	boolean_t	palloc = B_FALSE;
41940cb5e5dSvi 	int		r;
42040cb5e5dSvi 
42140cb5e5dSvi 	if (sip_msg == NULL || uri == NULL || header_name == NULL)
42240cb5e5dSvi 		return (EINVAL);
42340cb5e5dSvi 	if (display_name != NULL && !add_aquot)
42440cb5e5dSvi 		return (EINVAL);
42540cb5e5dSvi 	if (add_aquot) {
42640cb5e5dSvi 		t = sip_add_aquot_to_str(uri, &qalloc);
42740cb5e5dSvi 		if (t == NULL)
42840cb5e5dSvi 			return (ENOMEM);
42940cb5e5dSvi 	}
43040cb5e5dSvi 	if (tags != NULL) {
43140cb5e5dSvi 		int	plen;
43240cb5e5dSvi 
43340cb5e5dSvi 		if (params != NULL)
43440cb5e5dSvi 			return (EINVAL);
43540cb5e5dSvi 
43640cb5e5dSvi 		plen = strlen(SIP_TAG) + strlen(tags) + 1;
43740cb5e5dSvi 		params = malloc(plen);
43840cb5e5dSvi 		if (params == NULL)
43940cb5e5dSvi 			return (ENOMEM);
44040cb5e5dSvi 		(void) snprintf(params, plen, "%s%s", SIP_TAG, tags);
44140cb5e5dSvi 		params[plen - 1] = '\0';
44240cb5e5dSvi 		palloc = B_TRUE;
44340cb5e5dSvi 	}
44440cb5e5dSvi 	if (display_name == NULL) {
44540cb5e5dSvi 		r = sip_add_2strs_to_msg(sip_msg, header_name, " ", B_FALSE,
44640cb5e5dSvi 		    t, params, SIP_SP);
44740cb5e5dSvi 	} else {
44840cb5e5dSvi 		r = sip_add_2strs_to_msg(sip_msg, header_name, display_name,
44940cb5e5dSvi 		    B_TRUE, t, params, SIP_SP);
45040cb5e5dSvi 	}
45140cb5e5dSvi 	if (qalloc)
45240cb5e5dSvi 		free(t);
45340cb5e5dSvi 	if (palloc)
45440cb5e5dSvi 		free(params);
45540cb5e5dSvi 	return (r);
45640cb5e5dSvi }
45740cb5e5dSvi 
45840cb5e5dSvi /*
45940cb5e5dSvi  * Accept = "Accept" ":" (media-range [ accept-params ])
46040cb5e5dSvi  * media-range = ( "X/X" | (type "/" "*") | (type "/" subtype))*(";" parameter)
46140cb5e5dSvi  * accept-params = ";" "q" "=" qvalue *(accept-extension)
46240cb5e5dSvi  * accept-extension = ";" token [ "=" (token | quoted-str)
46340cb5e5dSvi  *
46440cb5e5dSvi  * function take two char ptrs - type and subtype - if any of them is NULL
46540cb5e5dSvi  * the corresponding value will be set to "*" in header
46640cb5e5dSvi  */
46740cb5e5dSvi int
sip_add_accept(sip_msg_t sip_msg,char * type,char * subtype,char * m_par,char * a_par)46840cb5e5dSvi sip_add_accept(sip_msg_t sip_msg, char *type, char *subtype, char *m_par,
46940cb5e5dSvi     char *a_par)
47040cb5e5dSvi {
47140cb5e5dSvi 	int		ret;
47240cb5e5dSvi 	char		*plist;
47340cb5e5dSvi 	int		size;
47440cb5e5dSvi 	boolean_t	alloc = B_FALSE;
47540cb5e5dSvi 
47640cb5e5dSvi 	if (type == NULL && subtype == NULL) {
47740cb5e5dSvi 		ret = sip_add_empty_hdr(sip_msg, SIP_ACCEPT);
47840cb5e5dSvi 		return (ret);
47940cb5e5dSvi 	}
48040cb5e5dSvi 
48140cb5e5dSvi 	if ((m_par != NULL) && (a_par != NULL)) {
48240cb5e5dSvi 		size = strlen(m_par) + strlen(a_par) + 2 * sizeof (char);
48340cb5e5dSvi 		plist = calloc(1, size * sizeof (char));
48440cb5e5dSvi 		(void) strncpy(plist, m_par, strlen(m_par));
48540cb5e5dSvi 		(void) strncat(plist, ";", 1);
48640cb5e5dSvi 		(void) strncat(plist, a_par, strlen(a_par));
48740cb5e5dSvi 		alloc = B_TRUE;
48840cb5e5dSvi 	} else if (m_par != NULL) {
48940cb5e5dSvi 		plist = m_par;
49040cb5e5dSvi 	} else
49140cb5e5dSvi 		plist = a_par;
49240cb5e5dSvi 
49340cb5e5dSvi 	if ((type != NULL) && (subtype != NULL)) {
49440cb5e5dSvi 		ret = sip_add_2strs_to_msg(sip_msg, SIP_ACCEPT, type, B_FALSE,
49540cb5e5dSvi 		    subtype, plist, SIP_SLASH);
49640cb5e5dSvi 	} else if (type != NULL) {
49740cb5e5dSvi 		ret = sip_add_2strs_to_msg(sip_msg, SIP_ACCEPT, type, B_FALSE,
49840cb5e5dSvi 		    "*", plist, SIP_SLASH);
49940cb5e5dSvi 	} else {
50040cb5e5dSvi 		ret = EINVAL;
50140cb5e5dSvi 	}
50240cb5e5dSvi 
50340cb5e5dSvi 	if (alloc == B_TRUE)
50440cb5e5dSvi 		free(plist);
50540cb5e5dSvi 
50640cb5e5dSvi 	return (ret);
50740cb5e5dSvi }
50840cb5e5dSvi 
50940cb5e5dSvi 
51040cb5e5dSvi /*
51140cb5e5dSvi  * Accept-Encoding = "Accept-Encoding" ":" 1#(codings [ ";" "q" "=" qval])
51240cb5e5dSvi  * codings = ( content-coding | "*" )
51340cb5e5dSvi  * content-coding   =  token
51440cb5e5dSvi  *
51540cb5e5dSvi  * function take one char ptr, if NULL value will be set to "*"
51640cb5e5dSvi  */
51740cb5e5dSvi int
sip_add_accept_enc(sip_msg_t sip_msg,char * code,char * plist)51840cb5e5dSvi sip_add_accept_enc(sip_msg_t sip_msg, char *code, char *plist)
51940cb5e5dSvi {
52040cb5e5dSvi 	int ret;
52140cb5e5dSvi 
52240cb5e5dSvi 	if (code == NULL) {
52340cb5e5dSvi 		ret = sip_add_str_to_msg(sip_msg, SIP_ACCEPT_ENCODE, "*", plist,
52440cb5e5dSvi 		    SIP_SEMI);
52540cb5e5dSvi 	} else {
52640cb5e5dSvi 		ret = sip_add_str_to_msg(sip_msg, SIP_ACCEPT_ENCODE, code,
52740cb5e5dSvi 		    plist, SIP_SEMI);
52840cb5e5dSvi 	}
52940cb5e5dSvi 	return (ret);
53040cb5e5dSvi }
53140cb5e5dSvi 
53240cb5e5dSvi /*
53340cb5e5dSvi  * Accept-Language = "Accept-Language" ":" 1#( language-range [ ";" "q""=" val])
53440cb5e5dSvi  * language-range = ( ( 1*8ALPHA *("-" 1*8ALPHA))|"*")
53540cb5e5dSvi  */
53640cb5e5dSvi int
sip_add_accept_lang(sip_msg_t sip_msg,char * lang,char * plist)53740cb5e5dSvi sip_add_accept_lang(sip_msg_t sip_msg, char *lang, char *plist)
53840cb5e5dSvi {
53940cb5e5dSvi 	int	ret;
54040cb5e5dSvi 
54140cb5e5dSvi 	if (lang == NULL) {
54240cb5e5dSvi 		ret = sip_add_empty_hdr(sip_msg, SIP_ACCEPT_LANG);
54340cb5e5dSvi 		return (ret);
54440cb5e5dSvi 	}
54540cb5e5dSvi 	ret = sip_add_str_to_msg(sip_msg, SIP_ACCEPT_LANG, lang, plist,
54640cb5e5dSvi 	    SIP_SEMI);
54740cb5e5dSvi 	return (ret);
54840cb5e5dSvi }
54940cb5e5dSvi 
55040cb5e5dSvi /*
55140cb5e5dSvi  * Alert-Info = "Alert-Info" ":" "<" URI ">"
55240cb5e5dSvi  */
55340cb5e5dSvi int
sip_add_alert_info(sip_msg_t sip_msg,char * alert,char * plist)55440cb5e5dSvi sip_add_alert_info(sip_msg_t sip_msg, char *alert, char *plist)
55540cb5e5dSvi {
55640cb5e5dSvi 	int		ret;
55740cb5e5dSvi 	char		*tmp;
55840cb5e5dSvi 	boolean_t	alloc;
55940cb5e5dSvi 
56040cb5e5dSvi 	if (alert == NULL)
56140cb5e5dSvi 		return (EINVAL);
56240cb5e5dSvi 	tmp = sip_add_aquot_to_str(alert, &alloc);
56340cb5e5dSvi 	if (tmp == NULL)
56440cb5e5dSvi 		return (ENOMEM);
56540cb5e5dSvi 	ret = sip_add_str_to_msg(sip_msg, SIP_ALERT_INFO, tmp, plist, SIP_SEMI);
56640cb5e5dSvi 	if (alloc)
56740cb5e5dSvi 		free(tmp);
56840cb5e5dSvi 	return (ret);
56940cb5e5dSvi }
57040cb5e5dSvi 
57140cb5e5dSvi /*
57240cb5e5dSvi  * Allow = "Allow" ":" method-name1[, method-name2..]
57340cb5e5dSvi  * method-name = "INVITE" | "ACK" | "OPTIONS" | "CANCEL" | "BYE"
57440cb5e5dSvi  */
57540cb5e5dSvi int
sip_add_allow(sip_msg_t sip_msg,sip_method_t method)57640cb5e5dSvi sip_add_allow(sip_msg_t sip_msg, sip_method_t method)
57740cb5e5dSvi {
57840cb5e5dSvi 	int	ret;
57940cb5e5dSvi 
58040cb5e5dSvi 	if (method == 0 || method >= MAX_SIP_METHODS)
58140cb5e5dSvi 		return (EINVAL);
58240cb5e5dSvi 	ret = sip_add_str_to_msg(sip_msg, SIP_ALLOW, sip_methods[method].name,
583*559f8b54SToomas Soome 	    NULL, 0);
58440cb5e5dSvi 	return (ret);
58540cb5e5dSvi }
58640cb5e5dSvi 
58740cb5e5dSvi /*
58840cb5e5dSvi  * Call-Info   =  "Call-Info" HCOLON info *(COMMA info)
58940cb5e5dSvi  * info        =  LAQUOT absoluteURI RAQUOT *( SEMI info-param)
59040cb5e5dSvi  * info-param  =  ( "purpose" EQUAL ( "icon" / "info"
59140cb5e5dSvi  *		/ "card" / token ) ) / generic-param
59240cb5e5dSvi  */
59340cb5e5dSvi int
sip_add_call_info(sip_msg_t sip_msg,char * uri,char * plist)59440cb5e5dSvi sip_add_call_info(sip_msg_t sip_msg, char *uri, char *plist)
59540cb5e5dSvi {
59640cb5e5dSvi 	char		*tmp;
59740cb5e5dSvi 	boolean_t	alloc;
59840cb5e5dSvi 	int		r;
59940cb5e5dSvi 
60040cb5e5dSvi 	if (uri == NULL)
60140cb5e5dSvi 		return (EINVAL);
60240cb5e5dSvi 	tmp = sip_add_aquot_to_str(uri, &alloc);
60340cb5e5dSvi 	if (tmp == NULL)
60440cb5e5dSvi 		return (ENOMEM);
60540cb5e5dSvi 	r = sip_add_str_to_msg(sip_msg, SIP_CALL_INFO, tmp, plist, SIP_SEMI);
60640cb5e5dSvi 	if (alloc)
60740cb5e5dSvi 		free(tmp);
60840cb5e5dSvi 	return (r);
60940cb5e5dSvi }
61040cb5e5dSvi 
61140cb5e5dSvi /*
61240cb5e5dSvi  * Content-Disposition   =  "Content-Disposition" HCOLON
61340cb5e5dSvi  *				disp-type *( SEMI disp-param )
61440cb5e5dSvi  * disp-type             =  "render" / "session" / "icon" / "alert"
61540cb5e5dSvi  *				/ disp-extension-token
61640cb5e5dSvi  * disp-param            =  handling-param / generic-param
61740cb5e5dSvi  * handling-param        =  "handling" EQUAL
61840cb5e5dSvi  *				( "optional" / "required"
61940cb5e5dSvi  *				/ other-handling )
62040cb5e5dSvi  * other-handling        =  token
62140cb5e5dSvi  * disp-extension-token  =  token
62240cb5e5dSvi  */
62340cb5e5dSvi int
sip_add_content_disp(sip_msg_t sip_msg,char * dis_type,char * plist)62440cb5e5dSvi sip_add_content_disp(sip_msg_t sip_msg, char *dis_type, char *plist)
62540cb5e5dSvi {
62640cb5e5dSvi 	int	ret;
62740cb5e5dSvi 
62840cb5e5dSvi 	if (dis_type == NULL)
62940cb5e5dSvi 		return (EINVAL);
63040cb5e5dSvi 
63140cb5e5dSvi 	ret = sip_add_str_to_msg(sip_msg, SIP_CONTENT_DIS, dis_type, plist,
63240cb5e5dSvi 	    SIP_SEMI);
63340cb5e5dSvi 	return (ret);
63440cb5e5dSvi }
63540cb5e5dSvi 
63640cb5e5dSvi /*
63740cb5e5dSvi  * Content-Encoding  =  ( "Content-Encoding" / "e" ) HCOLON
63840cb5e5dSvi  *			content-coding *(COMMA content-coding)
63940cb5e5dSvi  * content-coding   =  token
64040cb5e5dSvi  */
64140cb5e5dSvi int
sip_add_content_enc(sip_msg_t sip_msg,char * code)64240cb5e5dSvi sip_add_content_enc(sip_msg_t sip_msg, char *code)
64340cb5e5dSvi {
64440cb5e5dSvi 	int	ret;
64540cb5e5dSvi 
64640cb5e5dSvi 	if (code == NULL)
64740cb5e5dSvi 		return (EINVAL);
64840cb5e5dSvi 
649*559f8b54SToomas Soome 	ret = sip_add_str_to_msg(sip_msg, SIP_CONTENT_ENCODE, code, NULL, 0);
65040cb5e5dSvi 	return (ret);
65140cb5e5dSvi }
65240cb5e5dSvi 
65340cb5e5dSvi /*
65440cb5e5dSvi  * Content-Language  =  "Content-Language" HCOLON
65540cb5e5dSvi  *			language-tag *(COMMA language-tag)
65640cb5e5dSvi  * language-tag      =  primary-tag *( "-" subtag )
65740cb5e5dSvi  * primary-tag       =  1*8ALPHA
65840cb5e5dSvi  * subtag            =  1*8ALPHA
65940cb5e5dSvi  */
66040cb5e5dSvi int
sip_add_content_lang(sip_msg_t sip_msg,char * lang)66140cb5e5dSvi sip_add_content_lang(sip_msg_t sip_msg, char *lang)
66240cb5e5dSvi {
66340cb5e5dSvi 	int	ret;
66440cb5e5dSvi 
66540cb5e5dSvi 	if (lang == NULL)
66640cb5e5dSvi 		return (EINVAL);
667*559f8b54SToomas Soome 	ret = sip_add_str_to_msg(sip_msg, SIP_CONTENT_LANG, lang, NULL, 0);
66840cb5e5dSvi 	return (ret);
66940cb5e5dSvi }
67040cb5e5dSvi 
67140cb5e5dSvi /*
67240cb5e5dSvi  * Date          =  "Date" HCOLON SIP-date
67340cb5e5dSvi  * SIP-date      =  rfc1123-date
67440cb5e5dSvi  * rfc1123-date  =  wkday "," SP date1 SP time SP "GMT"
67540cb5e5dSvi  * date1         =  2DIGIT SP month SP 4DIGIT
676*559f8b54SToomas Soome  *			; day month year (e.g., 02 Jun 1982)
67740cb5e5dSvi  * time          =  2DIGIT ":" 2DIGIT ":" 2DIGIT
67840cb5e5dSvi  *			; 00:00:00 - 23:59:59
67940cb5e5dSvi  * wkday         =  "Mon" / "Tue" / "Wed"
68040cb5e5dSvi  *			/ "Thu" / "Fri" / "Sat" / "Sun"
68140cb5e5dSvi  * month         =  "Jan" / "Feb" / "Mar" / "Apr"
68240cb5e5dSvi  *			/ "May" / "Jun" / "Jul" / "Aug"
68340cb5e5dSvi  *			/ "Sep" / "Oct" / "Nov" / "Dec"
68440cb5e5dSvi  */
68540cb5e5dSvi int
sip_add_date(sip_msg_t sip_msg,char * date)68640cb5e5dSvi sip_add_date(sip_msg_t sip_msg, char *date)
68740cb5e5dSvi {
68840cb5e5dSvi 	int	ret;
68940cb5e5dSvi 
69040cb5e5dSvi 	if (date == NULL)
69140cb5e5dSvi 		return (EINVAL);
692*559f8b54SToomas Soome 	ret = sip_add_str_to_msg(sip_msg, SIP_DATE, date, NULL, 0);
69340cb5e5dSvi 	return (ret);
69440cb5e5dSvi }
69540cb5e5dSvi 
69640cb5e5dSvi /*
69740cb5e5dSvi  * Error-Info  =  "Error-Info" HCOLON error-uri *(COMMA error-uri)
69840cb5e5dSvi  * error-uri   =  LAQUOT absoluteURI RAQUOT *( SEMI generic-param )
69940cb5e5dSvi  */
70040cb5e5dSvi int
sip_add_error_info(sip_msg_t sip_msg,char * uri,char * plist)70140cb5e5dSvi sip_add_error_info(sip_msg_t sip_msg, char *uri, char *plist)
70240cb5e5dSvi {
70340cb5e5dSvi 	char		*tmp;
70440cb5e5dSvi 	boolean_t	alloc;
70540cb5e5dSvi 	int		r;
70640cb5e5dSvi 
70740cb5e5dSvi 	if (uri == NULL)
70840cb5e5dSvi 		return (EINVAL);
70940cb5e5dSvi 	tmp = sip_add_aquot_to_str(uri, &alloc);
71040cb5e5dSvi 	if (tmp == NULL)
71140cb5e5dSvi 		return (EINVAL);
71240cb5e5dSvi 
71340cb5e5dSvi 	r = sip_add_str_to_msg(sip_msg, SIP_ERROR_INFO, tmp, plist, SIP_SEMI);
71440cb5e5dSvi 	if (alloc)
71540cb5e5dSvi 		free(tmp);
71640cb5e5dSvi 	return (r);
71740cb5e5dSvi }
71840cb5e5dSvi 
71940cb5e5dSvi /*
72040cb5e5dSvi  * Expires     =  "Expires" HCOLON delta-seconds
72140cb5e5dSvi  * delta-seconds      =  1*DIGIT
72240cb5e5dSvi  */
72340cb5e5dSvi int
sip_add_expires(sip_msg_t sip_msg,int secs)72440cb5e5dSvi sip_add_expires(sip_msg_t sip_msg, int secs)
72540cb5e5dSvi {
72640cb5e5dSvi 	int	ret;
72740cb5e5dSvi 
72840cb5e5dSvi 	if (sip_msg == NULL || (int)secs < 0)
72940cb5e5dSvi 		return (EINVAL);
73040cb5e5dSvi 
73140cb5e5dSvi 	ret = sip_add_int_to_msg(sip_msg, SIP_EXPIRE, secs, NULL);
73240cb5e5dSvi 	return (ret);
73340cb5e5dSvi }
73440cb5e5dSvi 
73540cb5e5dSvi /*
73640cb5e5dSvi  * In-Reply-To  =  "In-Reply-To" HCOLON callid *(COMMA callid)
73740cb5e5dSvi  * callid   =  word [ "@" word ]
73840cb5e5dSvi  */
73940cb5e5dSvi int
sip_add_in_reply_to(sip_msg_t sip_msg,char * reply_id)74040cb5e5dSvi sip_add_in_reply_to(sip_msg_t sip_msg, char *reply_id)
74140cb5e5dSvi {
74240cb5e5dSvi 	int		r;
74340cb5e5dSvi 
74440cb5e5dSvi 	if (reply_id == NULL)
74540cb5e5dSvi 		return (EINVAL);
746*559f8b54SToomas Soome 	r = sip_add_str_to_msg(sip_msg, SIP_IN_REPLY_TO, reply_id, NULL, 0);
74740cb5e5dSvi 	return (r);
74840cb5e5dSvi }
74940cb5e5dSvi 
75040cb5e5dSvi /*
75140cb5e5dSvi  * RSeq          =  "RSeq" HCOLON response-num
75240cb5e5dSvi  */
75340cb5e5dSvi int
sip_add_rseq(sip_msg_t sip_msg,int resp_num)75440cb5e5dSvi sip_add_rseq(sip_msg_t sip_msg, int resp_num)
75540cb5e5dSvi {
75640cb5e5dSvi 	int	ret;
75740cb5e5dSvi 
75840cb5e5dSvi 	if (sip_msg == NULL || resp_num <= 0)
75940cb5e5dSvi 		return (EINVAL);
76040cb5e5dSvi 	ret = sip_add_int_to_msg(sip_msg, SIP_RSEQ, resp_num, NULL);
76140cb5e5dSvi 	return (ret);
76240cb5e5dSvi }
76340cb5e5dSvi 
76440cb5e5dSvi /*
76540cb5e5dSvi  * Min-Expires  =  "Min-Expires" HCOLON delta-seconds
76640cb5e5dSvi  */
76740cb5e5dSvi int
sip_add_min_expires(sip_msg_t sip_msg,int secs)76840cb5e5dSvi sip_add_min_expires(sip_msg_t sip_msg, int secs)
76940cb5e5dSvi {
77040cb5e5dSvi 	int	ret;
77140cb5e5dSvi 
77240cb5e5dSvi 	if (sip_msg == NULL || (int)secs < 0)
77340cb5e5dSvi 		return (EINVAL);
77440cb5e5dSvi 	ret = sip_add_int_to_msg(sip_msg, SIP_MIN_EXPIRE, secs, NULL);
77540cb5e5dSvi 	return (ret);
77640cb5e5dSvi }
77740cb5e5dSvi 
77840cb5e5dSvi /*
77940cb5e5dSvi  * MIME-Version  =  "MIME-Version" HCOLON 1*DIGIT "." 1*DIGIT
78040cb5e5dSvi  */
78140cb5e5dSvi int
sip_add_mime_version(sip_msg_t sip_msg,char * version)78240cb5e5dSvi sip_add_mime_version(sip_msg_t sip_msg, char *version)
78340cb5e5dSvi {
78440cb5e5dSvi 	int	ret;
78540cb5e5dSvi 
78640cb5e5dSvi 	if (version == NULL)
78740cb5e5dSvi 		return (EINVAL);
788*559f8b54SToomas Soome 	ret = sip_add_str_to_msg(sip_msg, SIP_MIME_VERSION, version, NULL, 0);
78940cb5e5dSvi 	return (ret);
79040cb5e5dSvi }
79140cb5e5dSvi 
79240cb5e5dSvi /*
79340cb5e5dSvi  * Organization  =  "Organization" HCOLON [TEXT-UTF8-TRIM]
79440cb5e5dSvi  */
79540cb5e5dSvi int
sip_add_org(sip_msg_t sip_msg,char * org)79640cb5e5dSvi sip_add_org(sip_msg_t sip_msg, char *org)
79740cb5e5dSvi {
79840cb5e5dSvi 	int	ret;
79940cb5e5dSvi 
80040cb5e5dSvi 	if (org == NULL) {
80140cb5e5dSvi 		ret = sip_add_empty_hdr(sip_msg, SIP_ORGANIZATION);
80240cb5e5dSvi 	} else {
80340cb5e5dSvi 		ret = sip_add_str_to_msg(sip_msg, SIP_ORGANIZATION, org, NULL,
804*559f8b54SToomas Soome 		    0);
80540cb5e5dSvi 	}
80640cb5e5dSvi 	return (ret);
80740cb5e5dSvi }
80840cb5e5dSvi 
80940cb5e5dSvi /*
81040cb5e5dSvi  * Priority        =  "Priority" HCOLON priority-value
81140cb5e5dSvi  * priority-value  =  "emergency" / "urgent" / "normal"
81240cb5e5dSvi  *			/ "non-urgent" / other-priority
81340cb5e5dSvi  * other-priority  =  token
81440cb5e5dSvi  */
81540cb5e5dSvi int
sip_add_priority(sip_msg_t sip_msg,char * prio)81640cb5e5dSvi sip_add_priority(sip_msg_t sip_msg, char *prio)
81740cb5e5dSvi {
81840cb5e5dSvi 	int	ret;
81940cb5e5dSvi 
82040cb5e5dSvi 	if (prio == NULL)
82140cb5e5dSvi 		return (EINVAL);
822*559f8b54SToomas Soome 	ret = sip_add_str_to_msg(sip_msg, SIP_PRIORITY, prio, NULL, 0);
82340cb5e5dSvi 
82440cb5e5dSvi 	return (ret);
82540cb5e5dSvi }
82640cb5e5dSvi 
82740cb5e5dSvi /*
82840cb5e5dSvi  * Reply-To      =  "Reply-To" HCOLON rplyto-spec
82940cb5e5dSvi  * rplyto-spec   =  ( name-addr / addr-spec )
83040cb5e5dSvi  *			*( SEMI rplyto-param )
83140cb5e5dSvi  * rplyto-param  =  generic-param
83240cb5e5dSvi  */
83340cb5e5dSvi int
sip_add_reply_to(sip_msg_t sip_msg,char * uname,char * addr,char * plist,boolean_t add_aquot)83440cb5e5dSvi sip_add_reply_to(sip_msg_t sip_msg, char *uname, char *addr, char *plist,
83540cb5e5dSvi     boolean_t add_aquot)
83640cb5e5dSvi {
83740cb5e5dSvi 	return (sip_add_name_aspec(sip_msg, uname, addr, NULL, add_aquot,
83840cb5e5dSvi 	    SIP_REPLYTO, plist));
83940cb5e5dSvi }
84040cb5e5dSvi 
84140cb5e5dSvi 
84240cb5e5dSvi /*
84340cb5e5dSvi  * Privacy-hdr  =  "Privacy" HCOLON priv-value *(";" priv-value)
84440cb5e5dSvi  * priv-value   =   "header" / "session" / "user" / "none" / "critical"
84540cb5e5dSvi  *			/ token
84640cb5e5dSvi  */
84740cb5e5dSvi int
sip_add_privacy(sip_msg_t sip_msg,char * priv_val)84840cb5e5dSvi sip_add_privacy(sip_msg_t sip_msg, char *priv_val)
84940cb5e5dSvi {
85040cb5e5dSvi 	int	ret;
85140cb5e5dSvi 
85240cb5e5dSvi 	if (priv_val == NULL)
85340cb5e5dSvi 		return (EINVAL);
854*559f8b54SToomas Soome 	ret = sip_add_str_to_msg(sip_msg, SIP_PRIVACY, priv_val, NULL, 0);
85540cb5e5dSvi 	return (ret);
85640cb5e5dSvi }
85740cb5e5dSvi 
85840cb5e5dSvi /*
85940cb5e5dSvi  * Require       =  "Require" HCOLON option-tag *(COMMA option-tag)
86040cb5e5dSvi  * option-tag     =  token
86140cb5e5dSvi  */
86240cb5e5dSvi int
sip_add_require(sip_msg_t sip_msg,char * req)86340cb5e5dSvi sip_add_require(sip_msg_t sip_msg, char *req)
86440cb5e5dSvi {
86540cb5e5dSvi 	int	ret;
86640cb5e5dSvi 
86740cb5e5dSvi 	if (req == NULL)
86840cb5e5dSvi 		return (EINVAL);
869*559f8b54SToomas Soome 	ret = sip_add_str_to_msg(sip_msg, SIP_REQUIRE, req, NULL, 0);
87040cb5e5dSvi 	return (ret);
87140cb5e5dSvi }
87240cb5e5dSvi 
87340cb5e5dSvi /*
87440cb5e5dSvi  * Retry-After  =  "Retry-After" HCOLON delta-seconds
87540cb5e5dSvi  *			[ comment ] *( SEMI retry-param )
87640cb5e5dSvi  * retry-param  =  ("duration" EQUAL delta-seconds)
87740cb5e5dSvi  *			/ generic-param
87840cb5e5dSvi  */
87940cb5e5dSvi int
sip_add_retry_after(sip_msg_t sip_msg,int secs,char * cmt,char * plist)88040cb5e5dSvi sip_add_retry_after(sip_msg_t sip_msg, int secs, char *cmt, char *plist)
88140cb5e5dSvi {
88240cb5e5dSvi 	int	r;
88340cb5e5dSvi 
88440cb5e5dSvi 	if (secs <= 0)
88540cb5e5dSvi 		return (EINVAL);
88640cb5e5dSvi 
88740cb5e5dSvi 	if (cmt == NULL) {
88840cb5e5dSvi 		r = sip_add_int_to_msg(sip_msg, SIP_RETRY_AFTER, secs, plist);
88940cb5e5dSvi 		return (r);
89040cb5e5dSvi 	}
89140cb5e5dSvi 
89240cb5e5dSvi 	r = sip_add_intstr_to_msg(sip_msg, SIP_RETRY_AFTER, secs, cmt, plist);
89340cb5e5dSvi 	return (r);
89440cb5e5dSvi }
89540cb5e5dSvi 
89640cb5e5dSvi /*
89740cb5e5dSvi  * Server           =  "Server" HCOLON server-val *(LWS server-val)
89840cb5e5dSvi  * server-val       =  product / comment
89940cb5e5dSvi  * product          =  token [SLASH product-version]
90040cb5e5dSvi  * product-version  =  token
90140cb5e5dSvi  */
90240cb5e5dSvi int
sip_add_server(sip_msg_t sip_msg,char * svr)90340cb5e5dSvi sip_add_server(sip_msg_t sip_msg, char *svr)
90440cb5e5dSvi {
90540cb5e5dSvi 	int	ret;
90640cb5e5dSvi 
90740cb5e5dSvi 	if (svr == NULL)
90840cb5e5dSvi 		return (EINVAL);
909*559f8b54SToomas Soome 	ret = sip_add_str_to_msg(sip_msg, SIP_SERVER, svr, NULL, 0);
91040cb5e5dSvi 	return (ret);
91140cb5e5dSvi }
91240cb5e5dSvi 
91340cb5e5dSvi /*
91440cb5e5dSvi  * Subject  =  ( "Subject" / "s" ) HCOLON [TEXT-UTF8-TRIM]
91540cb5e5dSvi  */
91640cb5e5dSvi int
sip_add_subject(sip_msg_t sip_msg,char * subject)91740cb5e5dSvi sip_add_subject(sip_msg_t sip_msg, char *subject)
91840cb5e5dSvi {
91940cb5e5dSvi 	int	ret;
92040cb5e5dSvi 
92140cb5e5dSvi 	if (subject == NULL) {
92240cb5e5dSvi 		ret = sip_add_empty_hdr(sip_msg, SIP_SUBJECT);
92340cb5e5dSvi 	} else {
924*559f8b54SToomas Soome 		ret = sip_add_str_to_msg(sip_msg, SIP_SUBJECT, subject,
925*559f8b54SToomas Soome 		    NULL, 0);
92640cb5e5dSvi 	}
92740cb5e5dSvi 	return (ret);
92840cb5e5dSvi }
92940cb5e5dSvi 
93040cb5e5dSvi /*
93140cb5e5dSvi  * Supported  =  ( "Supported" / "k" ) HCOLON
93240cb5e5dSvi  *		[option-tag *(COMMA option-tag)]
93340cb5e5dSvi  */
93440cb5e5dSvi int
sip_add_supported(sip_msg_t sip_msg,char * support)93540cb5e5dSvi sip_add_supported(sip_msg_t sip_msg, char *support)
93640cb5e5dSvi {
93740cb5e5dSvi 	int	ret;
93840cb5e5dSvi 
93940cb5e5dSvi 	if (support == NULL) {
94040cb5e5dSvi 		ret = sip_add_empty_hdr(sip_msg, SIP_SUPPORT);
94140cb5e5dSvi 	} else {
94240cb5e5dSvi 		ret = sip_add_str_to_msg(sip_msg, SIP_SUPPORT, support, NULL,
943*559f8b54SToomas Soome 		    0);
94440cb5e5dSvi 	}
94540cb5e5dSvi 	return (ret);
94640cb5e5dSvi }
94740cb5e5dSvi 
94840cb5e5dSvi /*
94940cb5e5dSvi  * Timestamp  =  "Timestamp" HCOLON 1*(DIGIT)
95040cb5e5dSvi  *		[ "." *(DIGIT) ] [ LWS delay ]
95140cb5e5dSvi  * delay      =  *(DIGIT) [ "." *(DIGIT) ]
95240cb5e5dSvi  */
95340cb5e5dSvi int
sip_add_tstamp(sip_msg_t sip_msg,char * time,char * delay)95440cb5e5dSvi sip_add_tstamp(sip_msg_t sip_msg, char *time, char *delay)
95540cb5e5dSvi {
95640cb5e5dSvi 	int	ret;
95740cb5e5dSvi 
95840cb5e5dSvi 	if (delay == NULL) {
959*559f8b54SToomas Soome 		ret = sip_add_str_to_msg(sip_msg, SIP_TIMESTAMP, time, NULL, 0);
96040cb5e5dSvi 	} else {
96140cb5e5dSvi 		ret = sip_add_2strs_to_msg(sip_msg, SIP_TIMESTAMP, time,
96240cb5e5dSvi 		    B_FALSE, delay, NULL, ' ');
96340cb5e5dSvi 	}
96440cb5e5dSvi 	return (ret);
96540cb5e5dSvi }
96640cb5e5dSvi 
96740cb5e5dSvi /*
96840cb5e5dSvi  * Unsupported  =  "Unsupported" HCOLON option-tag *(COMMA option-tag)
96940cb5e5dSvi  */
97040cb5e5dSvi int
sip_add_unsupported(sip_msg_t sip_msg,char * unsupport)97140cb5e5dSvi sip_add_unsupported(sip_msg_t sip_msg, char *unsupport)
97240cb5e5dSvi {
97340cb5e5dSvi 	int	ret;
97440cb5e5dSvi 
97540cb5e5dSvi 	if (unsupport == NULL)
97640cb5e5dSvi 		return (EINVAL);
977*559f8b54SToomas Soome 	ret = sip_add_str_to_msg(sip_msg, SIP_UNSUPPORT, unsupport, NULL, 0);
97840cb5e5dSvi 	return (ret);
97940cb5e5dSvi }
98040cb5e5dSvi 
98140cb5e5dSvi /*
98240cb5e5dSvi  * User-Agent  =  "User-Agent" HCOLON server-val *(LWS server-val)
98340cb5e5dSvi  */
98440cb5e5dSvi int
sip_add_user_agent(sip_msg_t sip_msg,char * usr)98540cb5e5dSvi sip_add_user_agent(sip_msg_t sip_msg, char *usr)
98640cb5e5dSvi {
98740cb5e5dSvi 	int	r;
98840cb5e5dSvi 
98940cb5e5dSvi 	if (usr == NULL)
99040cb5e5dSvi 		return (EINVAL);
991*559f8b54SToomas Soome 	r = sip_add_str_to_msg(sip_msg, SIP_USER_AGENT, usr, NULL, 0);
99240cb5e5dSvi 	return (r);
99340cb5e5dSvi }
99440cb5e5dSvi 
99540cb5e5dSvi /*
99640cb5e5dSvi  * Warning        =  "Warning" HCOLON warning-value *(COMMA warning-value)
99740cb5e5dSvi  * warning-value  =  warn-code SP warn-agent SP warn-text
99840cb5e5dSvi  * warn-code      =  3DIGIT
99940cb5e5dSvi  * warn-agent     =  hostport / pseudonym
100040cb5e5dSvi  *			;  the name or pseudonym of the server adding
100140cb5e5dSvi  *			;  the Warning header, for use in debugging
100240cb5e5dSvi  * warn-text      =  quoted-string
100340cb5e5dSvi  * pseudonym      =  token
100440cb5e5dSvi  */
100540cb5e5dSvi int
sip_add_warning(sip_msg_t sip_msg,int code,char * addr,char * msg)100640cb5e5dSvi sip_add_warning(sip_msg_t sip_msg, int code, char *addr, char *msg)
100740cb5e5dSvi {
100840cb5e5dSvi 	_sip_header_t	*new_header;
1009*559f8b54SToomas Soome 	int		header_size;
1010*559f8b54SToomas Soome 	_sip_msg_t	*_sip_msg;
101140cb5e5dSvi 	char		*hdr_name = SIP_WARNING;
101240cb5e5dSvi 
101340cb5e5dSvi 	if (sip_msg == NULL || addr == NULL || msg == NULL ||
1014450563a4SToomas Soome 	    addr[0] == '\0' || msg[0] == '\0' || code < 100 || code > 999) {
101540cb5e5dSvi 		return (EINVAL);
101640cb5e5dSvi 	}
101740cb5e5dSvi 
101840cb5e5dSvi 	_sip_msg = (_sip_msg_t *)sip_msg;
101940cb5e5dSvi 	(void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
102040cb5e5dSvi 	if (_sip_msg->sip_msg_cannot_be_modified) {
102140cb5e5dSvi 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
102240cb5e5dSvi 		return (ENOTSUP);
102340cb5e5dSvi 	}
102440cb5e5dSvi 
102540cb5e5dSvi 	header_size = strlen(hdr_name) + SIP_SPACE_LEN + sizeof (char) +
102640cb5e5dSvi 	    SIP_SPACE_LEN + sip_num_of_digits(code) + SIP_SPACE_LEN +
102740cb5e5dSvi 	    strlen(addr) + SIP_SPACE_LEN + sizeof (char) + strlen(msg) +
102840cb5e5dSvi 	    sizeof (char) + strlen(SIP_CRLF);
102940cb5e5dSvi 
103040cb5e5dSvi 	new_header = sip_new_header(header_size);
103140cb5e5dSvi 	if (new_header == NULL) {
103240cb5e5dSvi 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
103340cb5e5dSvi 		return (ENOMEM);
103440cb5e5dSvi 	}
103540cb5e5dSvi 
103640cb5e5dSvi 	(void) snprintf(new_header->sip_hdr_start, header_size + 1,
103740cb5e5dSvi 	    "%s %c %d %s \"%s\"%s", hdr_name, SIP_HCOLON, code, addr,
103840cb5e5dSvi 	    msg, SIP_CRLF);
103940cb5e5dSvi 	_sip_add_header(_sip_msg, new_header, B_TRUE, B_FALSE, NULL);
104040cb5e5dSvi 	if (_sip_msg->sip_msg_buf != NULL)
104140cb5e5dSvi 		_sip_msg->sip_msg_modified = B_TRUE;
104240cb5e5dSvi 	(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
104340cb5e5dSvi 
104440cb5e5dSvi 	return (0);
104540cb5e5dSvi }
104640cb5e5dSvi 
104740cb5e5dSvi /*
104840cb5e5dSvi  * RAck          =  "RAck" HCOLON response-num LWS CSeq-num LWS Method
104940cb5e5dSvi  * response-num  =  1*DIGIT
105040cb5e5dSvi  * CSeq-num      =  1*DIGIT
105140cb5e5dSvi  */
105240cb5e5dSvi int
sip_add_rack(sip_msg_t sip_msg,int resp_num,int cseq,sip_method_t method)105340cb5e5dSvi sip_add_rack(sip_msg_t sip_msg, int resp_num, int cseq, sip_method_t method)
105440cb5e5dSvi {
105540cb5e5dSvi 	_sip_header_t	*new_header;
1056*559f8b54SToomas Soome 	int		header_size;
1057*559f8b54SToomas Soome 	_sip_msg_t	*_sip_msg;
105840cb5e5dSvi 	char		*hdr_name = SIP_RACK;
105940cb5e5dSvi 
106040cb5e5dSvi 	if (sip_msg == NULL || resp_num <= 0 || cseq < 0 || method <= 0 ||
106140cb5e5dSvi 	    method >= MAX_SIP_METHODS) {
106240cb5e5dSvi 		return (EINVAL);
106340cb5e5dSvi 	}
106440cb5e5dSvi 
106540cb5e5dSvi 	_sip_msg = (_sip_msg_t *)sip_msg;
106640cb5e5dSvi 	(void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
106740cb5e5dSvi 	if (_sip_msg->sip_msg_cannot_be_modified) {
106840cb5e5dSvi 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
106940cb5e5dSvi 		return (ENOTSUP);
107040cb5e5dSvi 	}
107140cb5e5dSvi 
107240cb5e5dSvi 	header_size = strlen(hdr_name) + SIP_SPACE_LEN + sizeof (char) +
107340cb5e5dSvi 	    SIP_SPACE_LEN + sip_num_of_digits(resp_num) + SIP_SPACE_LEN +
107440cb5e5dSvi 	    sip_num_of_digits(cseq) + SIP_SPACE_LEN +
107540cb5e5dSvi 	    strlen(sip_methods[method].name) + strlen(SIP_CRLF);
107640cb5e5dSvi 
107740cb5e5dSvi 	new_header = sip_new_header(header_size);
107840cb5e5dSvi 	if (new_header == NULL) {
107940cb5e5dSvi 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
108040cb5e5dSvi 		return (ENOMEM);
108140cb5e5dSvi 	}
108240cb5e5dSvi 
108340cb5e5dSvi 	(void) snprintf(new_header->sip_hdr_start, header_size + 1,
108440cb5e5dSvi 	    "%s %c %d %d %s%s", hdr_name, SIP_HCOLON, resp_num, cseq,
108540cb5e5dSvi 	    sip_methods[method].name, SIP_CRLF);
108640cb5e5dSvi 
108740cb5e5dSvi 	_sip_add_header(_sip_msg, new_header, B_TRUE, B_FALSE, NULL);
108840cb5e5dSvi 	if (_sip_msg->sip_msg_buf != NULL)
108940cb5e5dSvi 		_sip_msg->sip_msg_modified = B_TRUE;
109040cb5e5dSvi 	(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
109140cb5e5dSvi 
109240cb5e5dSvi 	return (0);
109340cb5e5dSvi 
109440cb5e5dSvi }
109540cb5e5dSvi 
109640cb5e5dSvi /*
109740cb5e5dSvi  * Allow-Events =  ( "Allow-Events" / "u" ) HCOLON event-type
109840cb5e5dSvi  *			*(COMMA event-type)
109940cb5e5dSvi  */
110040cb5e5dSvi int
sip_add_allow_events(sip_msg_t sip_msg,char * t_event)110140cb5e5dSvi sip_add_allow_events(sip_msg_t sip_msg, char *t_event)
110240cb5e5dSvi {
1103*559f8b54SToomas Soome 	return (sip_add_str_to_msg(sip_msg, SIP_ALLOW_EVENTS, t_event,
1104*559f8b54SToomas Soome 	    NULL, 0));
110540cb5e5dSvi }
110640cb5e5dSvi 
110740cb5e5dSvi /*
110840cb5e5dSvi  * Event             =  ( "Event" / "o" ) HCOLON event-type
110940cb5e5dSvi  *			*( SEMI event-param )
111040cb5e5dSvi  * event-type        =  event-package *( "." event-template )
111140cb5e5dSvi  * event-package     =  token-nodot
111240cb5e5dSvi  * event-template    =  token-nodot
111340cb5e5dSvi  * token-nodot       =  1*( alphanum / "-"  / "!" / "%" / "*"
111440cb5e5dSvi  *			/ "_" / "+" / "`" / "'" / "~" )
111540cb5e5dSvi  * event-param       =  generic-param / ( "id" EQUAL token )
111640cb5e5dSvi  */
111740cb5e5dSvi int
sip_add_event(sip_msg_t sip_msg,char * t_event,char * plist)111840cb5e5dSvi sip_add_event(sip_msg_t sip_msg, char *t_event, char *plist)
111940cb5e5dSvi {
112040cb5e5dSvi 	return (sip_add_str_to_msg(sip_msg, SIP_EVENT, t_event, plist,
112140cb5e5dSvi 	    SIP_SEMI));
112240cb5e5dSvi }
112340cb5e5dSvi 
112440cb5e5dSvi /*
112540cb5e5dSvi  * Subscription-State   = "Subscription-State" HCOLON substate-value
1126*559f8b54SToomas Soome  *			*( SEMI subexp-params )
112740cb5e5dSvi  * substate-value       = "active" / "pending" / "terminated"
112840cb5e5dSvi  *			/ extension-substate
112940cb5e5dSvi  * extension-substate   = token
113040cb5e5dSvi  * subexp-params        =   ("reason" EQUAL event-reason-value)
113140cb5e5dSvi  *			/ ("expires" EQUAL delta-seconds)*
1132*559f8b54SToomas Soome  *			/ ("retry-after" EQUAL delta-seconds)
113340cb5e5dSvi  *			/ generic-param
113440cb5e5dSvi  * event-reason-value   =   "deactivated"
113540cb5e5dSvi  *				/ "probation"
113640cb5e5dSvi  *				/ "rejected"
113740cb5e5dSvi  *				/ "timeout"
113840cb5e5dSvi  *				/ "giveup"
113940cb5e5dSvi  *				/ "noresource"
114040cb5e5dSvi  *				/ event-reason-extension
114140cb5e5dSvi  * event-reason-extension = token
114240cb5e5dSvi  */
114340cb5e5dSvi int
sip_add_substate(sip_msg_t sip_msg,char * sub,char * plist)114440cb5e5dSvi sip_add_substate(sip_msg_t sip_msg, char *sub, char *plist)
114540cb5e5dSvi {
114640cb5e5dSvi 	return (sip_add_str_to_msg(sip_msg, SIP_SUBSCRIPTION_STATE, sub, plist,
114740cb5e5dSvi 	    SIP_SEMI));
114840cb5e5dSvi }
114940cb5e5dSvi 
115040cb5e5dSvi /*
115140cb5e5dSvi  * Authorization     =  "Authorization" HCOLON credentials
115240cb5e5dSvi  * credentials       =  ("Digest" LWS digest-response)
115340cb5e5dSvi  *			/ other-response
115440cb5e5dSvi  * digest-response   =  dig-resp *(COMMA dig-resp)
115540cb5e5dSvi  * dig-resp          =  username / realm / nonce / digest-uri
115640cb5e5dSvi  *			/ dresponse / algorithm / cnonce
115740cb5e5dSvi  *			/ opaque / message-qop
115840cb5e5dSvi  *			/ nonce-count / auth-param
115940cb5e5dSvi  * username          =  "username" EQUAL username-value
116040cb5e5dSvi  * username-value    =  quoted-string
116140cb5e5dSvi  * digest-uri        =  "uri" EQUAL LDQUOT digest-uri-value RDQUOT
116240cb5e5dSvi  * digest-uri-value  =  rquest-uri ; Equal to request-uri as specified
116340cb5e5dSvi  *			by HTTP/1.1
116440cb5e5dSvi  * message-qop       =  "qop" EQUAL qop-value
116540cb5e5dSvi  * cnonce            =  "cnonce" EQUAL cnonce-value
116640cb5e5dSvi  * cnonce-value      =  nonce-value
116740cb5e5dSvi  * nonce-count       =  "nc" EQUAL nc-value
116840cb5e5dSvi  * nc-value          =  8LHEX
116940cb5e5dSvi  * dresponse         =  "response" EQUAL request-digest
117040cb5e5dSvi  * request-digest    =  LDQUOT 32LHEX RDQUOT
117140cb5e5dSvi  * auth-param        =  auth-param-name EQUAL
1172*559f8b54SToomas Soome  *			( token / quoted-string )
117340cb5e5dSvi  * auth-param-name   =  token
117440cb5e5dSvi  * other-response    =  auth-scheme LWS auth-param
117540cb5e5dSvi  *			*(COMMA auth-param)
117640cb5e5dSvi  * auth-scheme       =  token
117740cb5e5dSvi  */
117840cb5e5dSvi int
sip_add_author(sip_msg_t sip_msg,char * scheme,char * param)117940cb5e5dSvi sip_add_author(sip_msg_t sip_msg, char *scheme, char *param)
118040cb5e5dSvi {
118140cb5e5dSvi 	return (sip_add_str_to_msg(sip_msg, SIP_AUTHOR, scheme, param, SIP_SP));
118240cb5e5dSvi }
118340cb5e5dSvi 
118440cb5e5dSvi /*
118540cb5e5dSvi  * Authentication-Info  =  "Authentication-Info" HCOLON ainfo
118640cb5e5dSvi  *				*(COMMA ainfo)
118740cb5e5dSvi  * ainfo                =  nextnonce / message-qop
118840cb5e5dSvi  *				/ response-auth / cnonce
118940cb5e5dSvi  *				/ nonce-count
119040cb5e5dSvi  * nextnonce            =  "nextnonce" EQUAL nonce-value
119140cb5e5dSvi  * response-auth        =  "rspauth" EQUAL response-digest
119240cb5e5dSvi  * response-digest      =  LDQUOT *LHEX RDQUOT
119340cb5e5dSvi  */
119440cb5e5dSvi int
sip_add_authen_info(sip_msg_t sip_msg,char * ainfo)119540cb5e5dSvi sip_add_authen_info(sip_msg_t sip_msg, char *ainfo)
119640cb5e5dSvi {
1197*559f8b54SToomas Soome 	return (sip_add_str_to_msg(sip_msg, SIP_AUTHEN_INFO, ainfo, NULL, 0));
119840cb5e5dSvi }
119940cb5e5dSvi 
120040cb5e5dSvi /*
120140cb5e5dSvi  * Proxy-Authenticate  =  "Proxy-Authenticate" HCOLON challenge
120240cb5e5dSvi  * challenge           =  ("Digest" LWS digest-cln *(COMMA digest-cln))
120340cb5e5dSvi  *				/ other-challenge
120440cb5e5dSvi  * other-challenge     =  auth-scheme LWS auth-param
1205*559f8b54SToomas Soome  *				*(COMMA auth-param)
120640cb5e5dSvi  * digest-cln          =  realm / domain / nonce
120740cb5e5dSvi  *				/ opaque / stale / algorithm
120840cb5e5dSvi  *				/ qop-options / auth-param
120940cb5e5dSvi  * realm               =  "realm" EQUAL realm-value
121040cb5e5dSvi  * realm-value         =  quoted-string
121140cb5e5dSvi  * domain              =  "domain" EQUAL LDQUOT URI
121240cb5e5dSvi  *				*( 1*SP URI ) RDQUOT
121340cb5e5dSvi  * URI                 =  absoluteURI / abs-path
121440cb5e5dSvi  * nonce               =  "nonce" EQUAL nonce-value
121540cb5e5dSvi  * nonce-value         =  quoted-string
121640cb5e5dSvi  * opaque              =  "opaque" EQUAL quoted-string
121740cb5e5dSvi  * stale               =  "stale" EQUAL ( "true" / "false" )
121840cb5e5dSvi  * algorithm           =  "algorithm" EQUAL ( "MD5" / "MD5-sess"
121940cb5e5dSvi  *			/ token )
122040cb5e5dSvi  * qop-options         =  "qop" EQUAL LDQUOT qop-value
122140cb5e5dSvi  *			*("," qop-value) RDQUOT
122240cb5e5dSvi  * qop-value           =  "auth" / "auth-int" / token
122340cb5e5dSvi  */
122440cb5e5dSvi int
sip_add_proxy_authen(sip_msg_t sip_msg,char * pascheme,char * paparam)122540cb5e5dSvi sip_add_proxy_authen(sip_msg_t sip_msg, char *pascheme, char *paparam)
122640cb5e5dSvi {
122740cb5e5dSvi 	return (sip_add_str_to_msg(sip_msg, SIP_PROXY_AUTHEN, pascheme, paparam,
122840cb5e5dSvi 	    SIP_SP));
122940cb5e5dSvi }
123040cb5e5dSvi 
123140cb5e5dSvi /*
123240cb5e5dSvi  * Proxy-Authorization  =  "Proxy-Authorization" HCOLON credentials
123340cb5e5dSvi  */
123440cb5e5dSvi int
sip_add_proxy_author(sip_msg_t sip_msg,char * paschem,char * paparam)123540cb5e5dSvi sip_add_proxy_author(sip_msg_t sip_msg, char *paschem, char *paparam)
123640cb5e5dSvi {
123740cb5e5dSvi 	return (sip_add_str_to_msg(sip_msg, SIP_PROXY_AUTHOR, paschem, paparam,
123840cb5e5dSvi 	    SIP_SP));
123940cb5e5dSvi }
124040cb5e5dSvi 
124140cb5e5dSvi /*
124240cb5e5dSvi  * Proxy-Require  =  "Proxy-Require" HCOLON option-tag
124340cb5e5dSvi  *			*(COMMA option-tag)
124440cb5e5dSvi  * option-tag     =  token
124540cb5e5dSvi  */
124640cb5e5dSvi int
sip_add_proxy_require(sip_msg_t sip_msg,char * opt)124740cb5e5dSvi sip_add_proxy_require(sip_msg_t sip_msg, char *opt)
124840cb5e5dSvi {
1249*559f8b54SToomas Soome 	return (sip_add_str_to_msg(sip_msg, SIP_PROXY_REQ, opt, NULL, 0));
125040cb5e5dSvi }
125140cb5e5dSvi 
125240cb5e5dSvi /*
125340cb5e5dSvi  * WWW-Authenticate  =  "WWW-Authenticate" HCOLON challenge
125440cb5e5dSvi  * extension-header  =  header-name HCOLON header-value
125540cb5e5dSvi  * header-name       =  token
125640cb5e5dSvi  * header-value      =  *(TEXT-UTF8char / UTF8-CONT / LWS)
125740cb5e5dSvi  * message-body  =  *OCTET
125840cb5e5dSvi  */
125940cb5e5dSvi int
sip_add_www_authen(sip_msg_t sip_msg,char * wascheme,char * waparam)126040cb5e5dSvi sip_add_www_authen(sip_msg_t sip_msg, char *wascheme, char *waparam)
126140cb5e5dSvi {
126240cb5e5dSvi 	return (sip_add_str_to_msg(sip_msg, SIP_WWW_AUTHEN, wascheme, waparam,
126340cb5e5dSvi 	    SIP_SP));
126440cb5e5dSvi }
126540cb5e5dSvi 
126640cb5e5dSvi /*
126740cb5e5dSvi  * Call-ID  =  ( "Call-ID" / "i" ) HCOLON callid
126840cb5e5dSvi  */
126940cb5e5dSvi int
sip_add_callid(sip_msg_t sip_msg,char * callid)127040cb5e5dSvi sip_add_callid(sip_msg_t sip_msg, char *callid)
127140cb5e5dSvi {
127240cb5e5dSvi 	int		ret;
127340cb5e5dSvi 	boolean_t	allocd = B_FALSE;
127440cb5e5dSvi 
127540cb5e5dSvi 	if (sip_msg == NULL || (callid != NULL && callid[0] == '\0'))
127640cb5e5dSvi 		return (EINVAL);
127740cb5e5dSvi 	if (callid == NULL) {
127840cb5e5dSvi 		callid = (char *)sip_guid();
127940cb5e5dSvi 		if (callid == NULL)
128040cb5e5dSvi 			return (ENOMEM);
128140cb5e5dSvi 		allocd = B_TRUE;
128240cb5e5dSvi 	}
1283*559f8b54SToomas Soome 	ret = sip_add_str_to_msg(sip_msg, SIP_CALL_ID, callid, NULL, 0);
128440cb5e5dSvi 	if (allocd)
128540cb5e5dSvi 		free(callid);
128640cb5e5dSvi 	return (ret);
128740cb5e5dSvi }
128840cb5e5dSvi 
128940cb5e5dSvi /*
129040cb5e5dSvi  * CSeq  =  "CSeq" HCOLON 1*DIGIT LWS Method
129140cb5e5dSvi  */
129240cb5e5dSvi int
sip_add_cseq(sip_msg_t sip_msg,sip_method_t method,uint32_t cseq)129340cb5e5dSvi sip_add_cseq(sip_msg_t sip_msg, sip_method_t method, uint32_t cseq)
129440cb5e5dSvi {
129540cb5e5dSvi 	int	r;
129640cb5e5dSvi 
129740cb5e5dSvi 	if (sip_msg == NULL || (int)cseq < 0 || method == 0 ||
129840cb5e5dSvi 	    method >= MAX_SIP_METHODS) {
129940cb5e5dSvi 		return (EINVAL);
130040cb5e5dSvi 	}
130140cb5e5dSvi 	r = sip_add_intstr_to_msg(sip_msg, SIP_CSEQ, cseq,
130240cb5e5dSvi 	    sip_methods[method].name, NULL);
130340cb5e5dSvi 	return (r);
130440cb5e5dSvi }
130540cb5e5dSvi 
130640cb5e5dSvi /*
130740cb5e5dSvi  * Via =  ( "Via" / "v" ) HCOLON via-parm *(COMMA via-parm)
130840cb5e5dSvi  * via-parm          =  sent-protocol LWS sent-by *( SEMI via-params )
130940cb5e5dSvi  * via-params        =  via-ttl / via-maddr
131040cb5e5dSvi  *                      / via-received / via-branch
131140cb5e5dSvi  *                      / via-extension
131240cb5e5dSvi  * via-ttl           =  "ttl" EQUAL ttl
131340cb5e5dSvi  * via-maddr         =  "maddr" EQUAL host
131440cb5e5dSvi  * via-received      =  "received" EQUAL (IPv4address / IPv6address)
131540cb5e5dSvi  * via-branch        =  "branch" EQUAL token
131640cb5e5dSvi  * via-extension     =  generic-param
131740cb5e5dSvi  * sent-protocol     =  protocol-name SLASH protocol-version
131840cb5e5dSvi  *                      SLASH transport
131940cb5e5dSvi  * protocol-name     =  "SIP" / token
132040cb5e5dSvi  * protocol-version  =  token
132140cb5e5dSvi  * transport         =  "UDP" / "TCP" / "TLS" / "SCTP"
132240cb5e5dSvi  *                      / other-transport
132340cb5e5dSvi  * sent-by           =  host [ COLON port ]
132440cb5e5dSvi  * ttl               =  1*3DIGIT ; 0 to 255
132540cb5e5dSvi  */
132640cb5e5dSvi _sip_header_t *
sip_create_via_hdr(char * sent_protocol_transport,char * sent_by_host,int sent_by_port,char * via_params)132740cb5e5dSvi sip_create_via_hdr(char *sent_protocol_transport, char *sent_by_host,
132840cb5e5dSvi     int sent_by_port, char *via_params)
132940cb5e5dSvi {
133040cb5e5dSvi 	_sip_header_t	*new_header;
133140cb5e5dSvi 	int		header_size;
133240cb5e5dSvi 	int		count;
133340cb5e5dSvi 
133440cb5e5dSvi 	header_size = strlen(SIP_VIA) + SIP_SPACE_LEN + sizeof (char) +
133540cb5e5dSvi 	    SIP_SPACE_LEN + strlen(SIP_VERSION) + sizeof (char) +
133640cb5e5dSvi 	    strlen(sent_protocol_transport) + SIP_SPACE_LEN +
133740cb5e5dSvi 	    strlen(sent_by_host) + strlen(SIP_CRLF);
133840cb5e5dSvi 
133940cb5e5dSvi 	if (sent_by_port > 0) {
134040cb5e5dSvi 		header_size += SIP_SPACE_LEN + sizeof (char) + SIP_SPACE_LEN +
134140cb5e5dSvi 		    sip_num_of_digits(sent_by_port);
134240cb5e5dSvi 	}
134340cb5e5dSvi 
134440cb5e5dSvi 	if (via_params != NULL) {
134540cb5e5dSvi 		header_size += SIP_SPACE_LEN + sizeof (char) +
134640cb5e5dSvi 		    strlen(via_params);
134740cb5e5dSvi 	}
134840cb5e5dSvi 	new_header = sip_new_header(header_size);
134940cb5e5dSvi 	if (new_header->sip_hdr_start == NULL)
135040cb5e5dSvi 		return (NULL);
135140cb5e5dSvi 	count = snprintf(new_header->sip_hdr_current, header_size + 1,
135240cb5e5dSvi 	    "%s %c %s/%s %s",
135340cb5e5dSvi 	    SIP_VIA, SIP_HCOLON, SIP_VERSION, sent_protocol_transport,
135440cb5e5dSvi 	    sent_by_host);
135540cb5e5dSvi 	new_header->sip_hdr_current += count;
135640cb5e5dSvi 	header_size -= count;
135740cb5e5dSvi 
135840cb5e5dSvi 	if (sent_by_port > 0) {
135940cb5e5dSvi 		count = snprintf(new_header->sip_hdr_current, header_size + 1,
136040cb5e5dSvi 		    " %c %d", SIP_HCOLON, sent_by_port);
136140cb5e5dSvi 		new_header->sip_hdr_current += count;
136240cb5e5dSvi 		header_size -= count;
136340cb5e5dSvi 	}
136440cb5e5dSvi 
136540cb5e5dSvi 	if (via_params != NULL) {
136640cb5e5dSvi 		count = snprintf(new_header->sip_hdr_current, header_size + 1,
136740cb5e5dSvi 		    " %c%s", SIP_SEMI, via_params);
136840cb5e5dSvi 		new_header->sip_hdr_current += count;
136940cb5e5dSvi 		header_size -= count;
137040cb5e5dSvi 	}
137140cb5e5dSvi 
137240cb5e5dSvi 	(void) snprintf(new_header->sip_hdr_current, header_size + 1,
137340cb5e5dSvi 	    "%s", SIP_CRLF);
137440cb5e5dSvi 	return (new_header);
137540cb5e5dSvi }
137640cb5e5dSvi 
137740cb5e5dSvi /*
137840cb5e5dSvi  * There can be multiple via headers we always append the header.
137940cb5e5dSvi  * We expect the via params to be a semi-colon separated list of parameters.
138040cb5e5dSvi  * We will add a semi-clone, before adding the list to the header.
138140cb5e5dSvi  */
138240cb5e5dSvi int
sip_add_via(sip_msg_t sip_msg,char * sent_protocol_transport,char * sent_by_host,int sent_by_port,char * via_params)138340cb5e5dSvi sip_add_via(sip_msg_t sip_msg, char *sent_protocol_transport,
138440cb5e5dSvi     char *sent_by_host, int sent_by_port, char *via_params)
138540cb5e5dSvi {
138640cb5e5dSvi 	_sip_header_t	*new_header;
138740cb5e5dSvi 	_sip_msg_t	*_sip_msg;
138840cb5e5dSvi 
138940cb5e5dSvi 	if (sip_msg == NULL || sent_protocol_transport == NULL ||
139040cb5e5dSvi 	    sent_by_host == NULL || sent_by_port < 0) {
139140cb5e5dSvi 		return (EINVAL);
139240cb5e5dSvi 	}
139340cb5e5dSvi 
139440cb5e5dSvi 	_sip_msg = (_sip_msg_t *)sip_msg;
139540cb5e5dSvi 	(void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
139640cb5e5dSvi 	if (_sip_msg->sip_msg_cannot_be_modified) {
139740cb5e5dSvi 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
139840cb5e5dSvi 		return (ENOTSUP);
139940cb5e5dSvi 	}
140040cb5e5dSvi 
140140cb5e5dSvi 	new_header = sip_create_via_hdr(sent_protocol_transport, sent_by_host,
140240cb5e5dSvi 	    sent_by_port, via_params);
140340cb5e5dSvi 	if (new_header == NULL) {
140440cb5e5dSvi 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
140540cb5e5dSvi 		return (ENOMEM);
140640cb5e5dSvi 	}
140740cb5e5dSvi 	_sip_add_header(_sip_msg, new_header, B_TRUE, B_FALSE, NULL);
140840cb5e5dSvi 	if (_sip_msg->sip_msg_buf != NULL)
140940cb5e5dSvi 		_sip_msg->sip_msg_modified = B_TRUE;
141040cb5e5dSvi 	(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
141140cb5e5dSvi 	return (0);
141240cb5e5dSvi }
141340cb5e5dSvi 
141440cb5e5dSvi /*
141540cb5e5dSvi  * Max-Forwards  =  "Max-Forwards" HCOLON 1*DIGIT
141640cb5e5dSvi  */
141740cb5e5dSvi int
sip_add_maxforward(sip_msg_t sip_msg,uint_t maxforward)141840cb5e5dSvi sip_add_maxforward(sip_msg_t sip_msg, uint_t maxforward)
141940cb5e5dSvi {
142040cb5e5dSvi 	if (sip_msg == NULL || (int)maxforward < 0)
142140cb5e5dSvi 		return (EINVAL);
142240cb5e5dSvi 	return (sip_add_int_to_msg(sip_msg, SIP_MAX_FORWARDS, maxforward,
142340cb5e5dSvi 	    NULL));
142440cb5e5dSvi }
142540cb5e5dSvi 
142640cb5e5dSvi /*
142740cb5e5dSvi  * Content-Type     =  ( "Content-Type" / "c" ) HCOLON media-type
142840cb5e5dSvi  * media-type       =  m-type SLASH m-subtype *(SEMI m-parameter)
142940cb5e5dSvi  * m-type           =  discrete-type / composite-type
143040cb5e5dSvi  * discrete-type    =  "text" / "image" / "audio" / "video"
143140cb5e5dSvi  *			/ "application" / extension-token
143240cb5e5dSvi  * composite-type   =  "message" / "multipart" / extension-token
143340cb5e5dSvi  * extension-token  =  ietf-token / x-token
143440cb5e5dSvi  * ietf-token       =  token
143540cb5e5dSvi  * x-token          =  "x-" token
143640cb5e5dSvi  * m-subtype        =  extension-token / iana-token
143740cb5e5dSvi  * iana-token       =  token
143840cb5e5dSvi  * m-parameter      =  m-attribute EQUAL m-value
143940cb5e5dSvi  * m-attribute      =  token
144040cb5e5dSvi  * m-value          =  token / quoted-string
144140cb5e5dSvi  */
144240cb5e5dSvi int
sip_add_content_type(sip_msg_t sip_msg,char * type,char * subtype)144340cb5e5dSvi sip_add_content_type(sip_msg_t sip_msg, char *type, char *subtype)
144440cb5e5dSvi {
144540cb5e5dSvi 	if (sip_msg == NULL || type == NULL || subtype == NULL)
144640cb5e5dSvi 		return (EINVAL);
144740cb5e5dSvi 	return (sip_add_2strs_to_msg(sip_msg, SIP_CONTENT_TYPE, type, B_FALSE,
144840cb5e5dSvi 	    subtype, NULL, SIP_SLASH));
144940cb5e5dSvi }
145040cb5e5dSvi 
145140cb5e5dSvi /*
145240cb5e5dSvi  * Content-Length  =  ( "Content-Length" / "l" ) HCOLON 1*DIGIT
145340cb5e5dSvi  */
145440cb5e5dSvi int
sip_add_content_length(_sip_msg_t * _sip_msg,int length)145540cb5e5dSvi sip_add_content_length(_sip_msg_t *_sip_msg, int length)
145640cb5e5dSvi {
145740cb5e5dSvi 	_sip_header_t	*new_header;
1458*559f8b54SToomas Soome 	int		header_size;
145940cb5e5dSvi 
146040cb5e5dSvi 	if (_sip_msg == NULL || length < 0)
146140cb5e5dSvi 		return (EINVAL);
146240cb5e5dSvi 	(void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
146340cb5e5dSvi 	if (_sip_msg->sip_msg_cannot_be_modified) {
146440cb5e5dSvi 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
146540cb5e5dSvi 		return (ENOTSUP);
146640cb5e5dSvi 	}
146740cb5e5dSvi 
146840cb5e5dSvi 	header_size = strlen(SIP_CONTENT_LENGTH) + SIP_SPACE_LEN +
146940cb5e5dSvi 	    sizeof (char) + SIP_SPACE_LEN + sip_num_of_digits(length) +
147040cb5e5dSvi 	    strlen(SIP_CRLF) + strlen(SIP_CRLF);
147140cb5e5dSvi 
147240cb5e5dSvi 	new_header = sip_new_header(header_size);
147340cb5e5dSvi 	if (new_header == NULL) {
147440cb5e5dSvi 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
147540cb5e5dSvi 		return (ENOMEM);
147640cb5e5dSvi 	}
147740cb5e5dSvi 	(void) snprintf(new_header->sip_hdr_start, header_size + 1,
147840cb5e5dSvi 	    "%s %c %u%s%s", SIP_CONTENT_LENGTH, SIP_HCOLON, length,
147940cb5e5dSvi 	    SIP_CRLF, SIP_CRLF);
148040cb5e5dSvi 
148140cb5e5dSvi 	_sip_add_header(_sip_msg, new_header, B_TRUE, B_FALSE, NULL);
148240cb5e5dSvi 	if (_sip_msg->sip_msg_buf != NULL)
148340cb5e5dSvi 		_sip_msg->sip_msg_modified = B_TRUE;
148440cb5e5dSvi 	(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
148540cb5e5dSvi 	return (0);
148640cb5e5dSvi }
148740cb5e5dSvi 
148840cb5e5dSvi 
148940cb5e5dSvi /*
149040cb5e5dSvi  * Contact = ("Contact" / "m" ) HCOLON
149140cb5e5dSvi  *		( STAR / (contact-param *(COMMA contact-param)))
149240cb5e5dSvi  * contact-param  =  (name-addr / addr-spec) *(SEMI contact-params)
149340cb5e5dSvi  * name-addr      =  [ display-name ] LAQUOT addr-spec RAQUOT
149440cb5e5dSvi  * addr-spec      =  SIP-URI / SIPS-URI / absoluteURI
149540cb5e5dSvi  * display-name   =  *(token LWS)/ quoted-string
149640cb5e5dSvi  * contact-params     =  c-p-q / c-p-expires
149740cb5e5dSvi  *                     / contact-extension
149840cb5e5dSvi  */
149940cb5e5dSvi int
sip_add_contact(sip_msg_t sip_msg,char * display_name,char * contact_uri,boolean_t add_aquot,char * contact_params)150040cb5e5dSvi sip_add_contact(sip_msg_t sip_msg, char *display_name, char *contact_uri,
150140cb5e5dSvi     boolean_t add_aquot, char *contact_params)
150240cb5e5dSvi {
150340cb5e5dSvi 	return (sip_add_name_aspec(sip_msg, display_name, contact_uri, NULL,
150440cb5e5dSvi 	    add_aquot, SIP_CONTACT, contact_params));
150540cb5e5dSvi }
150640cb5e5dSvi 
150740cb5e5dSvi /*
150840cb5e5dSvi  * From =  ( "From" / "f" ) HCOLON from-spec
150940cb5e5dSvi  * from-spec = ( name-addr / addr-spec )
151040cb5e5dSvi  *	*( SEMI from-param )
151140cb5e5dSvi  * from-param  =  tag-param / generic-param
151240cb5e5dSvi  * tag-param   =  "tag" EQUAL token
151340cb5e5dSvi  *
151440cb5e5dSvi  * Since there can be more than one tags, fromtags is a semi colon separated
151540cb5e5dSvi  * list of tags.
151640cb5e5dSvi  */
151740cb5e5dSvi int
sip_add_from(sip_msg_t sip_msg,char * display_name,char * from_uri,char * fromtags,boolean_t add_aquot,char * from_params)151840cb5e5dSvi sip_add_from(sip_msg_t sip_msg, char *display_name, char *from_uri,
151940cb5e5dSvi     char *fromtags, boolean_t add_aquot, char *from_params)
152040cb5e5dSvi {
152140cb5e5dSvi 	return (sip_add_name_aspec(sip_msg, display_name, from_uri, fromtags,
152240cb5e5dSvi 	    add_aquot, SIP_FROM, from_params));
152340cb5e5dSvi }
152440cb5e5dSvi 
152540cb5e5dSvi /*
152640cb5e5dSvi  * To =  ( "To" / "t" ) HCOLON ( name-addr
152740cb5e5dSvi  *	/ addr-spec ) *( SEMI to-param )
152840cb5e5dSvi  * to-param  =  tag-param / generic-param
152940cb5e5dSvi  */
153040cb5e5dSvi int
sip_add_to(sip_msg_t sip_msg,char * display_name,char * to_uri,char * totags,boolean_t add_aquot,char * to_params)153140cb5e5dSvi sip_add_to(sip_msg_t sip_msg, char *display_name, char *to_uri,
153240cb5e5dSvi     char *totags, boolean_t add_aquot, char *to_params)
153340cb5e5dSvi {
153440cb5e5dSvi 	return (sip_add_name_aspec(sip_msg, display_name, to_uri, totags,
153540cb5e5dSvi 	    add_aquot, SIP_TO, to_params));
153640cb5e5dSvi }
153740cb5e5dSvi 
153840cb5e5dSvi /*
153940cb5e5dSvi  * Route        =  "Route" HCOLON route-param *(COMMA route-param)
154040cb5e5dSvi  * route-param  =  name-addr *( SEMI rr-param )
154140cb5e5dSvi  */
154240cb5e5dSvi int
sip_add_route(sip_msg_t sip_msg,char * display_name,char * uri,char * route_params)154340cb5e5dSvi sip_add_route(sip_msg_t sip_msg, char *display_name, char *uri,
154440cb5e5dSvi     char *route_params)
154540cb5e5dSvi {
154640cb5e5dSvi 	return (sip_add_name_aspec(sip_msg, display_name, uri, NULL, B_TRUE,
154740cb5e5dSvi 	    SIP_ROUTE, route_params));
154840cb5e5dSvi }
154940cb5e5dSvi 
155040cb5e5dSvi /*
155140cb5e5dSvi  * Record-Route  =  "Record-Route" HCOLON rec-route *(COMMA rec-route)
155240cb5e5dSvi  * rec-route     =  name-addr *( SEMI rr-param )
155340cb5e5dSvi  * rr-param      =  generic-param
155440cb5e5dSvi  */
155540cb5e5dSvi int
sip_add_record_route(sip_msg_t sip_msg,char * display_name,char * uri,char * route_params)155640cb5e5dSvi sip_add_record_route(sip_msg_t sip_msg, char *display_name, char *uri,
155740cb5e5dSvi     char *route_params)
155840cb5e5dSvi {
155940cb5e5dSvi 	return (sip_add_name_aspec(sip_msg, display_name, uri, NULL, B_TRUE,
156040cb5e5dSvi 	    SIP_RECORD_ROUTE, route_params));
156140cb5e5dSvi }
156240cb5e5dSvi 
156340cb5e5dSvi 
156440cb5e5dSvi /*
156540cb5e5dSvi  * PAssertedID = "P-Asserted-Identity" HCOLON PAssertedID-value
156640cb5e5dSvi  *			*(COMMA PAssertedID-value)
156740cb5e5dSvi  * PAssertedID-value = name-addr / addr-spec
156840cb5e5dSvi  */
156940cb5e5dSvi int
sip_add_passertedid(sip_msg_t sip_msg,char * display_name,char * addr,boolean_t add_aquot)157040cb5e5dSvi sip_add_passertedid(sip_msg_t sip_msg, char *display_name, char *addr,
157140cb5e5dSvi     boolean_t add_aquot)
157240cb5e5dSvi {
157340cb5e5dSvi 	return (sip_add_name_aspec(sip_msg, display_name, addr, NULL, add_aquot,
157440cb5e5dSvi 	    SIP_PASSERTEDID, NULL));
157540cb5e5dSvi }
157640cb5e5dSvi 
157740cb5e5dSvi /*
157840cb5e5dSvi  * PPreferredID = "P-Preferred-Identity" HCOLON PPreferredID-value
157940cb5e5dSvi  *			*(COMMA PPreferredID-value)
158040cb5e5dSvi  * PPreferredID-value = name-addr / addr-spec
158140cb5e5dSvi  */
158240cb5e5dSvi int
sip_add_ppreferredid(sip_msg_t sip_msg,char * display_name,char * addr,boolean_t add_aquot)158340cb5e5dSvi sip_add_ppreferredid(sip_msg_t sip_msg, char *display_name, char *addr,
158440cb5e5dSvi     boolean_t add_aquot)
158540cb5e5dSvi {
158640cb5e5dSvi 	return (sip_add_name_aspec(sip_msg, display_name, addr, NULL, add_aquot,
158740cb5e5dSvi 	    SIP_PPREFERREDID, NULL));
158840cb5e5dSvi }
1589