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