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 /*
23*2c2c4183Svi * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
2440cb5e5dSvi * Use is subject to license terms.
2540cb5e5dSvi */
2640cb5e5dSvi
27*2c2c4183Svi #include <stdio.h>
28*2c2c4183Svi #include <stdlib.h>
29*2c2c4183Svi #include <assert.h>
30*2c2c4183Svi #include <ctype.h>
31*2c2c4183Svi #include <errno.h>
32*2c2c4183Svi #include <strings.h>
33*2c2c4183Svi #include <pthread.h>
34*2c2c4183Svi #include <sip.h>
35*2c2c4183Svi
3640cb5e5dSvi #include "sip_msg.h"
3740cb5e5dSvi #include "sip_miscdefs.h"
38*2c2c4183Svi #include "sip_parse_uri.h"
3940cb5e5dSvi #include "sip_xaction.h"
4040cb5e5dSvi
4140cb5e5dSvi #define SIP_BUF_SIZE 128
4240cb5e5dSvi
4340cb5e5dSvi /*
4440cb5e5dSvi * Find the header named header, consecutive calls with old_header
4540cb5e5dSvi * passed in will return next header of the same type.
4640cb5e5dSvi * If no name is passed the first header is returned. consectutive calls
4740cb5e5dSvi * with no name but an old header will return the next header.
4840cb5e5dSvi */
4940cb5e5dSvi const struct sip_header *
sip_get_header(sip_msg_t sip_msg,char * header_name,sip_header_t old_header,int * error)5040cb5e5dSvi sip_get_header(sip_msg_t sip_msg, char *header_name, sip_header_t old_header,
5140cb5e5dSvi int *error)
5240cb5e5dSvi {
5340cb5e5dSvi _sip_msg_t *_sip_msg;
5440cb5e5dSvi const struct sip_header *sip_hdr;
5540cb5e5dSvi
5640cb5e5dSvi if (error != NULL)
5740cb5e5dSvi *error = 0;
5840cb5e5dSvi if (sip_msg == NULL) {
5940cb5e5dSvi if (error != NULL)
6040cb5e5dSvi *error = EINVAL;
6140cb5e5dSvi return (NULL);
6240cb5e5dSvi }
6340cb5e5dSvi _sip_msg = (_sip_msg_t *)sip_msg;
6440cb5e5dSvi (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
6540cb5e5dSvi sip_hdr = (sip_header_t)sip_search_for_header((_sip_msg_t *)sip_msg,
6640cb5e5dSvi header_name, (_sip_header_t *)old_header);
6740cb5e5dSvi (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
6840cb5e5dSvi if (sip_hdr == NULL && error != NULL)
6940cb5e5dSvi *error = EINVAL;
7040cb5e5dSvi return (sip_hdr);
7140cb5e5dSvi }
7240cb5e5dSvi
7340cb5e5dSvi /*
7440cb5e5dSvi * Return the request line as a string. Caller releases the returned string.
7540cb5e5dSvi */
7640cb5e5dSvi char *
sip_reqline_to_str(sip_msg_t sip_msg,int * error)7740cb5e5dSvi sip_reqline_to_str(sip_msg_t sip_msg, int *error)
7840cb5e5dSvi {
7940cb5e5dSvi char *reqstr;
8040cb5e5dSvi
8140cb5e5dSvi if (error != NULL)
8240cb5e5dSvi *error = 0;
8340cb5e5dSvi if (sip_msg == NULL || !sip_msg_is_request(sip_msg, error)) {
8440cb5e5dSvi if (error != NULL)
8540cb5e5dSvi *error = EINVAL;
8640cb5e5dSvi return (NULL);
8740cb5e5dSvi }
8840cb5e5dSvi reqstr = _sip_startline_to_str((_sip_msg_t *)sip_msg, error);
8940cb5e5dSvi return (reqstr);
9040cb5e5dSvi }
9140cb5e5dSvi
9240cb5e5dSvi /*
9340cb5e5dSvi * Return the response line as a string. Caller releases the returned string.
9440cb5e5dSvi */
9540cb5e5dSvi char *
sip_respline_to_str(sip_msg_t sip_msg,int * error)9640cb5e5dSvi sip_respline_to_str(sip_msg_t sip_msg, int *error)
9740cb5e5dSvi {
9840cb5e5dSvi char *respstr;
9940cb5e5dSvi
10040cb5e5dSvi if (error != NULL)
10140cb5e5dSvi *error = 0;
10240cb5e5dSvi if (sip_msg == NULL || sip_msg_is_request(sip_msg, error)) {
10340cb5e5dSvi if (error != NULL)
10440cb5e5dSvi *error = EINVAL;
10540cb5e5dSvi return (NULL);
10640cb5e5dSvi }
10740cb5e5dSvi respstr = _sip_startline_to_str((_sip_msg_t *)sip_msg, error);
10840cb5e5dSvi return (respstr);
10940cb5e5dSvi }
11040cb5e5dSvi
11140cb5e5dSvi /*
11240cb5e5dSvi * return the first value of the header
11340cb5e5dSvi */
11440cb5e5dSvi const struct sip_value *
sip_get_header_value(const struct sip_header * sip_header,int * error)11540cb5e5dSvi sip_get_header_value(const struct sip_header *sip_header, int *error)
11640cb5e5dSvi {
11740cb5e5dSvi _sip_header_t *_sip_header;
11840cb5e5dSvi sip_parsed_header_t *sip_parsed_header;
11940cb5e5dSvi int ret = 0;
12040cb5e5dSvi const struct sip_value *value;
12140cb5e5dSvi
12240cb5e5dSvi if (error != NULL)
12340cb5e5dSvi *error = 0;
12440cb5e5dSvi if (sip_header == NULL) {
12540cb5e5dSvi if (error != NULL)
12640cb5e5dSvi *error = EINVAL;
12740cb5e5dSvi return (NULL);
12840cb5e5dSvi }
12940cb5e5dSvi _sip_header = (_sip_header_t *)sip_header;
13040cb5e5dSvi if (_sip_header->sip_hdr_sipmsg != NULL) {
13140cb5e5dSvi (void) pthread_mutex_lock(
13240cb5e5dSvi &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
13340cb5e5dSvi }
13440cb5e5dSvi if (_sip_header->sip_header_state == SIP_HEADER_DELETED) {
13540cb5e5dSvi if (_sip_header->sip_hdr_sipmsg != NULL) {
13640cb5e5dSvi (void) pthread_mutex_unlock(
13740cb5e5dSvi &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
13840cb5e5dSvi }
13940cb5e5dSvi if (error != NULL)
14040cb5e5dSvi *error = EINVAL;
14140cb5e5dSvi return (NULL);
14240cb5e5dSvi }
14340cb5e5dSvi ret = _sip_header->sip_header_functions->header_parse_func(
14440cb5e5dSvi _sip_header, &sip_parsed_header);
14540cb5e5dSvi if (_sip_header->sip_hdr_sipmsg != NULL) {
14640cb5e5dSvi (void) pthread_mutex_unlock
14740cb5e5dSvi (&_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
14840cb5e5dSvi }
14940cb5e5dSvi if (error != NULL)
15040cb5e5dSvi *error = ret;
15140cb5e5dSvi
15240cb5e5dSvi if (ret != 0)
15340cb5e5dSvi return (NULL);
15440cb5e5dSvi value = (sip_header_value_t)sip_parsed_header->value;
15540cb5e5dSvi while (value != NULL && value->value_state == SIP_VALUE_DELETED)
15640cb5e5dSvi value = value->next;
15740cb5e5dSvi if (value != NULL && value->value_state == SIP_VALUE_BAD &&
15840cb5e5dSvi error != NULL) {
15940cb5e5dSvi *error = EPROTO;
16040cb5e5dSvi }
16140cb5e5dSvi return ((sip_header_value_t)value);
16240cb5e5dSvi }
16340cb5e5dSvi
16440cb5e5dSvi /*
16540cb5e5dSvi * Return the next value of the header.
16640cb5e5dSvi */
16740cb5e5dSvi const struct sip_value *
sip_get_next_value(sip_header_value_t old_value,int * error)16840cb5e5dSvi sip_get_next_value(sip_header_value_t old_value, int *error)
16940cb5e5dSvi {
17040cb5e5dSvi const struct sip_value *value;
17140cb5e5dSvi
17240cb5e5dSvi if (error != NULL)
17340cb5e5dSvi *error = 0;
17440cb5e5dSvi if (old_value == NULL || old_value->next == NULL) {
17540cb5e5dSvi if (error != NULL)
17640cb5e5dSvi *error = EINVAL;
17740cb5e5dSvi return (NULL);
17840cb5e5dSvi }
17940cb5e5dSvi /*
18040cb5e5dSvi * We never free the deleted values so no need to hold a lock.
18140cb5e5dSvi */
18240cb5e5dSvi value = (sip_header_value_t)old_value->next;
18340cb5e5dSvi while (value != NULL && value->value_state == SIP_VALUE_DELETED)
18440cb5e5dSvi value = value->next;
18540cb5e5dSvi if (value != NULL && value->value_state == SIP_VALUE_BAD &&
18640cb5e5dSvi error != NULL) {
18740cb5e5dSvi *error = EPROTO;
18840cb5e5dSvi }
18940cb5e5dSvi return ((sip_header_value_t)value);
19040cb5e5dSvi }
19140cb5e5dSvi
19240cb5e5dSvi /*
19340cb5e5dSvi * Given a SIP message, delete the header "header_name".
19440cb5e5dSvi */
19540cb5e5dSvi int
sip_delete_header_by_name(sip_msg_t msg,char * header_name)19640cb5e5dSvi sip_delete_header_by_name(sip_msg_t msg, char *header_name)
19740cb5e5dSvi {
19840cb5e5dSvi _sip_msg_t *_msg = (_sip_msg_t *)msg;
19940cb5e5dSvi sip_header_t sip_hdr;
20040cb5e5dSvi _sip_header_t *_sip_hdr;
20140cb5e5dSvi
20240cb5e5dSvi if (_msg == NULL || header_name == NULL)
20340cb5e5dSvi return (EINVAL);
20440cb5e5dSvi (void) pthread_mutex_lock(&_msg->sip_msg_mutex);
20540cb5e5dSvi if (_msg->sip_msg_cannot_be_modified) {
20640cb5e5dSvi (void) pthread_mutex_unlock(&_msg->sip_msg_mutex);
20740cb5e5dSvi return (EPERM);
20840cb5e5dSvi }
20940cb5e5dSvi sip_hdr = (sip_header_t)sip_search_for_header(_msg, header_name, NULL);
21040cb5e5dSvi if (sip_hdr == NULL) {
21140cb5e5dSvi (void) pthread_mutex_unlock(&_msg->sip_msg_mutex);
21240cb5e5dSvi return (EINVAL);
21340cb5e5dSvi }
21440cb5e5dSvi _sip_hdr = (_sip_header_t *)sip_hdr;
21540cb5e5dSvi _sip_hdr->sip_header_state = SIP_HEADER_DELETED;
21640cb5e5dSvi _sip_hdr->sip_hdr_sipmsg->sip_msg_len -= _sip_hdr->sip_hdr_end -
21740cb5e5dSvi _sip_hdr->sip_hdr_start;
21840cb5e5dSvi assert(_sip_hdr->sip_hdr_sipmsg->sip_msg_len >= 0);
21940cb5e5dSvi if (_msg->sip_msg_buf != NULL)
22040cb5e5dSvi _msg->sip_msg_modified = B_TRUE;
22140cb5e5dSvi (void) pthread_mutex_unlock(&_msg->sip_msg_mutex);
22240cb5e5dSvi
22340cb5e5dSvi return (0);
22440cb5e5dSvi }
22540cb5e5dSvi
22640cb5e5dSvi /*
22740cb5e5dSvi * Mark the header as deleted.
22840cb5e5dSvi */
22940cb5e5dSvi int
sip_delete_header(sip_header_t sip_header)23040cb5e5dSvi sip_delete_header(sip_header_t sip_header)
23140cb5e5dSvi {
23240cb5e5dSvi _sip_header_t *_sip_header;
23340cb5e5dSvi
23440cb5e5dSvi if (sip_header == NULL)
23540cb5e5dSvi return (EINVAL);
23640cb5e5dSvi _sip_header = (_sip_header_t *)sip_header;
23740cb5e5dSvi (void) pthread_mutex_lock(&_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
23840cb5e5dSvi if (_sip_header->sip_hdr_sipmsg->sip_msg_cannot_be_modified) {
23940cb5e5dSvi (void) pthread_mutex_unlock
24040cb5e5dSvi (&_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
24140cb5e5dSvi return (EPERM);
24240cb5e5dSvi }
24340cb5e5dSvi if (_sip_header->sip_header_state == SIP_HEADER_DELETED) {
24440cb5e5dSvi (void) pthread_mutex_unlock(
24540cb5e5dSvi &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
24640cb5e5dSvi return (EINVAL);
24740cb5e5dSvi }
24840cb5e5dSvi _sip_header->sip_header_state = SIP_HEADER_DELETED;
24940cb5e5dSvi _sip_header->sip_hdr_sipmsg->sip_msg_len -= _sip_header->sip_hdr_end -
25040cb5e5dSvi _sip_header->sip_hdr_start;
25140cb5e5dSvi assert(_sip_header->sip_hdr_sipmsg->sip_msg_len >= 0);
25240cb5e5dSvi if (_sip_header->sip_hdr_sipmsg->sip_msg_buf != NULL)
25340cb5e5dSvi _sip_header->sip_hdr_sipmsg->sip_msg_modified = B_TRUE;
25440cb5e5dSvi (void) pthread_mutex_unlock
25540cb5e5dSvi (&_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
25640cb5e5dSvi return (0);
25740cb5e5dSvi }
25840cb5e5dSvi
25940cb5e5dSvi /*
26040cb5e5dSvi * Mark the value as deleted.
26140cb5e5dSvi */
26240cb5e5dSvi int
sip_delete_value(sip_header_t sip_header,sip_header_value_t sip_header_value)26340cb5e5dSvi sip_delete_value(sip_header_t sip_header, sip_header_value_t sip_header_value)
26440cb5e5dSvi {
26540cb5e5dSvi _sip_header_t *_sip_header;
26640cb5e5dSvi sip_value_t *_sip_header_value;
26740cb5e5dSvi int vlen;
26840cb5e5dSvi char *c;
26940cb5e5dSvi
27040cb5e5dSvi if (sip_header == NULL || sip_header_value == NULL)
27140cb5e5dSvi return (EINVAL);
27240cb5e5dSvi _sip_header = (_sip_header_t *)sip_header;
27340cb5e5dSvi (void) pthread_mutex_lock(&_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
27440cb5e5dSvi if (_sip_header->sip_hdr_sipmsg->sip_msg_cannot_be_modified) {
27540cb5e5dSvi (void) pthread_mutex_unlock(&_sip_header->
27640cb5e5dSvi sip_hdr_sipmsg->sip_msg_mutex);
27740cb5e5dSvi return (EPERM);
27840cb5e5dSvi }
27940cb5e5dSvi if (_sip_header->sip_header_state == SIP_HEADER_DELETED) {
28040cb5e5dSvi (void) pthread_mutex_unlock(
28140cb5e5dSvi &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
28240cb5e5dSvi return (EINVAL);
28340cb5e5dSvi }
28440cb5e5dSvi _sip_header_value = (sip_value_t *)sip_header_value;
28540cb5e5dSvi if (_sip_header_value->value_state == SIP_VALUE_DELETED) {
28640cb5e5dSvi (void) pthread_mutex_unlock(
28740cb5e5dSvi &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
28840cb5e5dSvi return (EINVAL);
28940cb5e5dSvi }
29040cb5e5dSvi _sip_header->sip_header_state = SIP_HEADER_DELETED_VAL;
29140cb5e5dSvi _sip_header_value->value_state = SIP_VALUE_DELETED;
29240cb5e5dSvi vlen = _sip_header_value->value_end - _sip_header_value->value_start;
29340cb5e5dSvi if (_sip_header->sip_hdr_parsed->value == _sip_header_value) {
29440cb5e5dSvi c = _sip_header_value->value_start;
29540cb5e5dSvi while (*c-- != SIP_HCOLON)
29640cb5e5dSvi vlen++;
29740cb5e5dSvi } else {
29840cb5e5dSvi c = _sip_header_value->value_start;
29940cb5e5dSvi while (*c-- != SIP_COMMA)
30040cb5e5dSvi vlen++;
30140cb5e5dSvi }
30240cb5e5dSvi if (_sip_header_value->next == NULL) {
30340cb5e5dSvi sip_value_t *value = _sip_header->sip_hdr_parsed->value;
30440cb5e5dSvi boolean_t crlf_present = B_FALSE;
30540cb5e5dSvi char *s;
30640cb5e5dSvi
30740cb5e5dSvi while (value != NULL && value != _sip_header_value) {
30840cb5e5dSvi crlf_present = B_FALSE;
30940cb5e5dSvi
31040cb5e5dSvi if (value->value_state == SIP_VALUE_DELETED) {
31140cb5e5dSvi value = value->next;
31240cb5e5dSvi continue;
31340cb5e5dSvi }
31440cb5e5dSvi s = value->value_end;
31540cb5e5dSvi while (s != value->value_start) {
31640cb5e5dSvi if (*s == '\r' && strncmp(s, SIP_CRLF,
31740cb5e5dSvi strlen(SIP_CRLF)) == 0) {
31840cb5e5dSvi crlf_present = B_TRUE;
31940cb5e5dSvi break;
32040cb5e5dSvi }
32140cb5e5dSvi s--;
32240cb5e5dSvi }
32340cb5e5dSvi value = value->next;
32440cb5e5dSvi }
32540cb5e5dSvi if (!crlf_present) {
32640cb5e5dSvi c = _sip_header_value->value_end;
32740cb5e5dSvi while (*c-- != '\r')
32840cb5e5dSvi vlen--;
32940cb5e5dSvi assert(vlen > 0);
33040cb5e5dSvi }
33140cb5e5dSvi }
33240cb5e5dSvi _sip_header->sip_hdr_sipmsg->sip_msg_len -= vlen;
33340cb5e5dSvi if (_sip_header->sip_hdr_sipmsg->sip_msg_buf != NULL)
33440cb5e5dSvi _sip_header->sip_hdr_sipmsg->sip_msg_modified = B_TRUE;
33540cb5e5dSvi (void) pthread_mutex_unlock
33640cb5e5dSvi (&_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
33740cb5e5dSvi return (0);
33840cb5e5dSvi }
33940cb5e5dSvi
34040cb5e5dSvi /*
34140cb5e5dSvi * Given a param list, check if a param name exists.
34240cb5e5dSvi */
34340cb5e5dSvi boolean_t
sip_is_param_present(const sip_param_t * param_list,char * param_name,int param_len)34440cb5e5dSvi sip_is_param_present(const sip_param_t *param_list, char *param_name,
34540cb5e5dSvi int param_len)
34640cb5e5dSvi {
34740cb5e5dSvi const sip_param_t *param = param_list;
34840cb5e5dSvi
34940cb5e5dSvi while (param != NULL) {
35040cb5e5dSvi if (param->param_name.sip_str_len == param_len &&
35140cb5e5dSvi strncasecmp(param->param_name.sip_str_ptr, param_name,
35240cb5e5dSvi param_len) == 0) {
35340cb5e5dSvi return (B_TRUE);
35440cb5e5dSvi }
35540cb5e5dSvi param = param->param_next;
35640cb5e5dSvi }
35740cb5e5dSvi return (B_FALSE);
35840cb5e5dSvi }
35940cb5e5dSvi
36040cb5e5dSvi
36140cb5e5dSvi /*
36240cb5e5dSvi * Given a value header return the value of the named param.
36340cb5e5dSvi */
36440cb5e5dSvi const sip_str_t *
sip_get_param_value(sip_header_value_t header_value,char * param_name,int * error)36540cb5e5dSvi sip_get_param_value(sip_header_value_t header_value, char *param_name,
36640cb5e5dSvi int *error)
36740cb5e5dSvi {
36840cb5e5dSvi sip_value_t *_sip_header_value;
36940cb5e5dSvi sip_param_t *sip_param;
37040cb5e5dSvi
37140cb5e5dSvi if (error != NULL)
37240cb5e5dSvi *error = 0;
37340cb5e5dSvi if (header_value == NULL || param_name == NULL) {
37440cb5e5dSvi if (error != NULL)
37540cb5e5dSvi *error = EINVAL;
37640cb5e5dSvi return (NULL);
37740cb5e5dSvi }
37840cb5e5dSvi _sip_header_value = (sip_value_t *)header_value;
37940cb5e5dSvi if (_sip_header_value->value_state == SIP_VALUE_DELETED) {
38040cb5e5dSvi if (error != NULL)
38140cb5e5dSvi *error = EINVAL;
38240cb5e5dSvi return (NULL);
38340cb5e5dSvi }
38440cb5e5dSvi if (_sip_header_value->param_list == NULL) {
38540cb5e5dSvi if (error != NULL)
38640cb5e5dSvi *error = EINVAL;
38740cb5e5dSvi return (NULL);
38840cb5e5dSvi }
38940cb5e5dSvi sip_param = sip_get_param_from_list(_sip_header_value->param_list,
39040cb5e5dSvi param_name);
39140cb5e5dSvi if (sip_param != NULL)
39240cb5e5dSvi return (&sip_param->param_value);
39340cb5e5dSvi return (NULL);
39440cb5e5dSvi }
39540cb5e5dSvi
39640cb5e5dSvi /*
39740cb5e5dSvi * Return the list of params in the header
39840cb5e5dSvi */
39940cb5e5dSvi const sip_param_t *
sip_get_params(sip_header_value_t header_value,int * error)40040cb5e5dSvi sip_get_params(sip_header_value_t header_value, int *error)
40140cb5e5dSvi {
40240cb5e5dSvi sip_value_t *sip_header_value;
40340cb5e5dSvi
40440cb5e5dSvi if (error != NULL)
40540cb5e5dSvi *error = 0;
40640cb5e5dSvi if (header_value == NULL) {
40740cb5e5dSvi if (error != NULL)
40840cb5e5dSvi *error = EINVAL;
40940cb5e5dSvi return (NULL);
41040cb5e5dSvi }
41140cb5e5dSvi sip_header_value = (sip_value_t *)header_value;
41240cb5e5dSvi if (sip_header_value->value_state == SIP_VALUE_DELETED) {
41340cb5e5dSvi if (error != NULL)
41440cb5e5dSvi *error = EINVAL;
41540cb5e5dSvi return (NULL);
41640cb5e5dSvi }
41740cb5e5dSvi return (sip_header_value->param_list);
41840cb5e5dSvi }
41940cb5e5dSvi
42040cb5e5dSvi /*
42140cb5e5dSvi * Return true if this is a SIP request
42240cb5e5dSvi */
42340cb5e5dSvi boolean_t
sip_msg_is_request(sip_msg_t sip_msg,int * error)42440cb5e5dSvi sip_msg_is_request(sip_msg_t sip_msg, int *error)
42540cb5e5dSvi {
42640cb5e5dSvi _sip_msg_t *_sip_msg;
42740cb5e5dSvi sip_message_type_t *sip_msg_info;
42840cb5e5dSvi boolean_t ret;
42940cb5e5dSvi
43040cb5e5dSvi if (error != NULL)
43140cb5e5dSvi *error = 0;
43240cb5e5dSvi if (sip_msg == NULL) {
43340cb5e5dSvi if (error != NULL)
43440cb5e5dSvi *error = EINVAL;
43540cb5e5dSvi return (B_FALSE);
43640cb5e5dSvi }
43740cb5e5dSvi _sip_msg = (_sip_msg_t *)sip_msg;
43840cb5e5dSvi (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
43940cb5e5dSvi if (_sip_msg->sip_msg_req_res == NULL) {
44040cb5e5dSvi (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
44140cb5e5dSvi if (error != NULL)
44240cb5e5dSvi *error = EINVAL;
44340cb5e5dSvi return (B_FALSE);
44440cb5e5dSvi }
44540cb5e5dSvi sip_msg_info = _sip_msg->sip_msg_req_res;
44640cb5e5dSvi ret = sip_msg_info->is_request;
44740cb5e5dSvi (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
44840cb5e5dSvi return (ret);
44940cb5e5dSvi }
45040cb5e5dSvi
45140cb5e5dSvi /*
45240cb5e5dSvi * Return true if this is a SIP response
45340cb5e5dSvi */
45440cb5e5dSvi boolean_t
sip_msg_is_response(sip_msg_t sip_msg,int * error)45540cb5e5dSvi sip_msg_is_response(sip_msg_t sip_msg, int *error)
45640cb5e5dSvi {
45740cb5e5dSvi boolean_t is_resp;
45840cb5e5dSvi _sip_msg_t *_sip_msg;
45940cb5e5dSvi sip_message_type_t *sip_msg_info;
46040cb5e5dSvi
46140cb5e5dSvi if (error != NULL)
46240cb5e5dSvi *error = 0;
46340cb5e5dSvi if (sip_msg == NULL) {
46440cb5e5dSvi if (error != NULL)
46540cb5e5dSvi *error = EINVAL;
46640cb5e5dSvi return (B_FALSE);
46740cb5e5dSvi }
46840cb5e5dSvi _sip_msg = (_sip_msg_t *)sip_msg;
46940cb5e5dSvi (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
47040cb5e5dSvi if (_sip_msg->sip_msg_req_res == NULL) {
47140cb5e5dSvi (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
47240cb5e5dSvi if (error != NULL)
47340cb5e5dSvi *error = EINVAL;
47440cb5e5dSvi return (B_FALSE);
47540cb5e5dSvi }
47640cb5e5dSvi sip_msg_info = _sip_msg->sip_msg_req_res;
47740cb5e5dSvi is_resp = !sip_msg_info->is_request;
47840cb5e5dSvi (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
47940cb5e5dSvi return (is_resp);
48040cb5e5dSvi }
48140cb5e5dSvi
48240cb5e5dSvi /*
48340cb5e5dSvi * Return the method in the request line
48440cb5e5dSvi */
48540cb5e5dSvi sip_method_t
sip_get_request_method(sip_msg_t sip_msg,int * error)48640cb5e5dSvi sip_get_request_method(sip_msg_t sip_msg, int *error)
48740cb5e5dSvi {
48840cb5e5dSvi _sip_msg_t *_sip_msg;
48940cb5e5dSvi sip_message_type_t *sip_msg_info;
49040cb5e5dSvi sip_method_t ret = -1;
49140cb5e5dSvi
49240cb5e5dSvi if (error != NULL)
49340cb5e5dSvi *error = 0;
49440cb5e5dSvi if (sip_msg == NULL) {
49540cb5e5dSvi if (error != NULL)
49640cb5e5dSvi *error = EINVAL;
49740cb5e5dSvi return (ret);
49840cb5e5dSvi }
49940cb5e5dSvi _sip_msg = (_sip_msg_t *)sip_msg;
50040cb5e5dSvi (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
50140cb5e5dSvi sip_msg_info = _sip_msg->sip_msg_req_res;
50240cb5e5dSvi if (_sip_msg->sip_msg_req_res == NULL) {
50340cb5e5dSvi (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
50440cb5e5dSvi if (error != NULL)
50540cb5e5dSvi *error = EINVAL;
50640cb5e5dSvi return (ret);
50740cb5e5dSvi }
50840cb5e5dSvi if (sip_msg_info->is_request)
50940cb5e5dSvi ret = sip_msg_info->sip_req_method;
51040cb5e5dSvi else if (error != NULL)
51140cb5e5dSvi *error = EINVAL;
51240cb5e5dSvi (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
51340cb5e5dSvi return (ret);
51440cb5e5dSvi }
51540cb5e5dSvi
51640cb5e5dSvi /*
51740cb5e5dSvi * Return the URI from the request line
51840cb5e5dSvi */
51940cb5e5dSvi const sip_str_t *
sip_get_request_uri_str(sip_msg_t sip_msg,int * error)52040cb5e5dSvi sip_get_request_uri_str(sip_msg_t sip_msg, int *error)
52140cb5e5dSvi {
52240cb5e5dSvi _sip_msg_t *_sip_msg;
52340cb5e5dSvi sip_message_type_t *sip_msg_info;
52440cb5e5dSvi sip_str_t *ret = NULL;
52540cb5e5dSvi struct sip_uri *parsed_uri;
52640cb5e5dSvi
52740cb5e5dSvi if (error != NULL)
52840cb5e5dSvi *error = 0;
52940cb5e5dSvi if (sip_msg == NULL) {
53040cb5e5dSvi if (error != NULL)
53140cb5e5dSvi *error = EINVAL;
53240cb5e5dSvi return (NULL);
53340cb5e5dSvi }
53440cb5e5dSvi _sip_msg = (_sip_msg_t *)sip_msg;
53540cb5e5dSvi (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
53640cb5e5dSvi if (_sip_msg->sip_msg_req_res == NULL) {
53740cb5e5dSvi (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
53840cb5e5dSvi if (error != NULL)
53940cb5e5dSvi *error = EINVAL;
54040cb5e5dSvi return (NULL);
54140cb5e5dSvi }
54240cb5e5dSvi sip_msg_info = _sip_msg->sip_msg_req_res;
54340cb5e5dSvi if (sip_msg_info->is_request)
54440cb5e5dSvi ret = &sip_msg_info->sip_req_uri;
54540cb5e5dSvi (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
54640cb5e5dSvi
54740cb5e5dSvi /*
54840cb5e5dSvi * If the error is required, check the validity of the URI via
54940cb5e5dSvi * sip_uri_parse().
55040cb5e5dSvi */
55140cb5e5dSvi if (error != NULL) {
55240cb5e5dSvi parsed_uri = sip_parse_uri(ret, error);
55340cb5e5dSvi if (parsed_uri != NULL)
55440cb5e5dSvi sip_free_parsed_uri((sip_uri_t)parsed_uri);
55540cb5e5dSvi }
55640cb5e5dSvi return (ret);
55740cb5e5dSvi }
55840cb5e5dSvi
55940cb5e5dSvi /*
56040cb5e5dSvi * Return the response code
56140cb5e5dSvi */
56240cb5e5dSvi int
sip_get_response_code(sip_msg_t sip_msg,int * error)56340cb5e5dSvi sip_get_response_code(sip_msg_t sip_msg, int *error)
56440cb5e5dSvi {
56540cb5e5dSvi _sip_msg_t *_sip_msg;
56640cb5e5dSvi sip_message_type_t *sip_msg_info;
56740cb5e5dSvi int ret = -1;
56840cb5e5dSvi
56940cb5e5dSvi if (error != NULL)
57040cb5e5dSvi *error = 0;
57140cb5e5dSvi if (sip_msg == NULL) {
57240cb5e5dSvi if (error != NULL)
57340cb5e5dSvi *error = EINVAL;
57440cb5e5dSvi return (ret);
57540cb5e5dSvi }
57640cb5e5dSvi _sip_msg = (_sip_msg_t *)sip_msg;
57740cb5e5dSvi (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
57840cb5e5dSvi if (_sip_msg->sip_msg_req_res == NULL) {
57940cb5e5dSvi (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
58040cb5e5dSvi if (error != NULL)
58140cb5e5dSvi *error = EINVAL;
58240cb5e5dSvi return (ret);
58340cb5e5dSvi }
58440cb5e5dSvi sip_msg_info = _sip_msg->sip_msg_req_res;
58540cb5e5dSvi if (!sip_msg_info->is_request)
58640cb5e5dSvi ret = sip_msg_info->sip_resp_code;
58740cb5e5dSvi else if (error != NULL)
58840cb5e5dSvi *error = EINVAL;
58940cb5e5dSvi (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
59040cb5e5dSvi return (ret);
59140cb5e5dSvi }
59240cb5e5dSvi
59340cb5e5dSvi /*
59440cb5e5dSvi * Get the response phrase
59540cb5e5dSvi */
59640cb5e5dSvi const sip_str_t *
sip_get_response_phrase(sip_msg_t sip_msg,int * error)59740cb5e5dSvi sip_get_response_phrase(sip_msg_t sip_msg, int *error)
59840cb5e5dSvi {
59940cb5e5dSvi _sip_msg_t *_sip_msg;
60040cb5e5dSvi sip_message_type_t *sip_msg_info;
60140cb5e5dSvi sip_str_t *ret = NULL;
60240cb5e5dSvi
60340cb5e5dSvi if (error != NULL)
60440cb5e5dSvi *error = 0;
60540cb5e5dSvi if (sip_msg == NULL) {
60640cb5e5dSvi if (error != NULL)
60740cb5e5dSvi *error = EINVAL;
60840cb5e5dSvi return (ret);
60940cb5e5dSvi }
61040cb5e5dSvi _sip_msg = (_sip_msg_t *)sip_msg;
61140cb5e5dSvi (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
61240cb5e5dSvi if (_sip_msg->sip_msg_req_res == NULL) {
61340cb5e5dSvi (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
61440cb5e5dSvi if (error != NULL)
61540cb5e5dSvi *error = EINVAL;
61640cb5e5dSvi return (ret);
61740cb5e5dSvi }
61840cb5e5dSvi sip_msg_info = _sip_msg->sip_msg_req_res;
61940cb5e5dSvi (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
62040cb5e5dSvi if (!sip_msg_info->is_request) {
62140cb5e5dSvi if (sip_msg_info->sip_resp_phrase_len == 0)
62240cb5e5dSvi ret = NULL;
62340cb5e5dSvi else
62440cb5e5dSvi ret = &sip_msg_info->sip_resp_phrase;
62540cb5e5dSvi } else if (error != NULL) {
62640cb5e5dSvi *error = EINVAL;
62740cb5e5dSvi }
62840cb5e5dSvi return (ret);
62940cb5e5dSvi }
63040cb5e5dSvi
63140cb5e5dSvi /*
63240cb5e5dSvi * Get the SIP version string
63340cb5e5dSvi */
63440cb5e5dSvi const sip_str_t *
sip_get_sip_version(sip_msg_t sip_msg,int * error)63540cb5e5dSvi sip_get_sip_version(sip_msg_t sip_msg, int *error)
63640cb5e5dSvi {
63740cb5e5dSvi _sip_msg_t *_sip_msg;
63840cb5e5dSvi sip_message_type_t *sip_msg_info;
63940cb5e5dSvi sip_str_t *ret = NULL;
64040cb5e5dSvi
64140cb5e5dSvi if (error != NULL)
64240cb5e5dSvi *error = 0;
64340cb5e5dSvi if (sip_msg == NULL) {
64440cb5e5dSvi if (error != NULL)
64540cb5e5dSvi *error = EINVAL;
64640cb5e5dSvi return (ret);
64740cb5e5dSvi }
64840cb5e5dSvi _sip_msg = (_sip_msg_t *)sip_msg;
64940cb5e5dSvi (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
65040cb5e5dSvi if (_sip_msg->sip_msg_req_res == NULL) {
65140cb5e5dSvi (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
65240cb5e5dSvi if (error != NULL)
65340cb5e5dSvi *error = EINVAL;
65440cb5e5dSvi return (ret);
65540cb5e5dSvi }
65640cb5e5dSvi sip_msg_info = _sip_msg->sip_msg_req_res;
65740cb5e5dSvi (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
65840cb5e5dSvi ret = &sip_msg_info->sip_proto_version.version;
65940cb5e5dSvi return (ret);
66040cb5e5dSvi }
66140cb5e5dSvi
66240cb5e5dSvi /*
66340cb5e5dSvi * Return the length of the SIP message
66440cb5e5dSvi */
66540cb5e5dSvi int
sip_get_msg_len(sip_msg_t sip_msg,int * error)66640cb5e5dSvi sip_get_msg_len(sip_msg_t sip_msg, int *error)
66740cb5e5dSvi {
66840cb5e5dSvi _sip_msg_t *_sip_msg;
66940cb5e5dSvi
67040cb5e5dSvi if (error != NULL)
67140cb5e5dSvi *error = 0;
67240cb5e5dSvi if (sip_msg == NULL) {
67340cb5e5dSvi if (error != NULL)
67440cb5e5dSvi *error = EINVAL;
67540cb5e5dSvi return (-1);
67640cb5e5dSvi }
67740cb5e5dSvi _sip_msg = (_sip_msg_t *)sip_msg;
67840cb5e5dSvi
67940cb5e5dSvi return (_sip_msg->sip_msg_len);
68040cb5e5dSvi }
68140cb5e5dSvi
68240cb5e5dSvi /*
68340cb5e5dSvi * Get content as a string. Caller frees the string
68440cb5e5dSvi */
68540cb5e5dSvi char *
sip_get_content(sip_msg_t sip_msg,int * error)68640cb5e5dSvi sip_get_content(sip_msg_t sip_msg, int *error)
68740cb5e5dSvi {
68840cb5e5dSvi _sip_msg_t *_sip_msg;
68940cb5e5dSvi sip_content_t *sip_content;
69040cb5e5dSvi char *content;
69140cb5e5dSvi int len;
69240cb5e5dSvi char *p;
69340cb5e5dSvi
69440cb5e5dSvi if (error != NULL)
69540cb5e5dSvi *error = 0;
69640cb5e5dSvi
69740cb5e5dSvi if (sip_msg == NULL) {
69840cb5e5dSvi if (error != NULL)
69940cb5e5dSvi *error = EINVAL;
70040cb5e5dSvi return (NULL);
70140cb5e5dSvi }
70240cb5e5dSvi _sip_msg = (_sip_msg_t *)sip_msg;
70340cb5e5dSvi (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
70440cb5e5dSvi if (_sip_msg->sip_msg_content == NULL) {
70540cb5e5dSvi (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
70640cb5e5dSvi if (error != NULL)
70740cb5e5dSvi *error = EINVAL;
70840cb5e5dSvi return (NULL);
70940cb5e5dSvi }
71040cb5e5dSvi content = malloc(_sip_msg->sip_msg_content_len + 1);
71140cb5e5dSvi if (content == NULL) {
71240cb5e5dSvi (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
71340cb5e5dSvi if (error != NULL)
71440cb5e5dSvi *error = ENOMEM;
71540cb5e5dSvi return (NULL);
71640cb5e5dSvi }
71740cb5e5dSvi p = content;
71840cb5e5dSvi sip_content = _sip_msg->sip_msg_content;
71940cb5e5dSvi while (sip_content != NULL) {
72040cb5e5dSvi len = sip_content->sip_content_end -
72140cb5e5dSvi sip_content->sip_content_start;
72240cb5e5dSvi (void) strncpy(p, sip_content->sip_content_start, len);
72340cb5e5dSvi p += len;
72440cb5e5dSvi sip_content = sip_content->sip_content_next;
72540cb5e5dSvi }
72640cb5e5dSvi content[_sip_msg->sip_msg_content_len] = '\0';
72740cb5e5dSvi (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
72840cb5e5dSvi return (content);
72940cb5e5dSvi }
73040cb5e5dSvi
73140cb5e5dSvi /*
73240cb5e5dSvi * copy sip_header with param, if any, to sip_msg
73340cb5e5dSvi */
73440cb5e5dSvi int
sip_copy_header(sip_msg_t sip_msg,sip_header_t sip_header,char * param)73540cb5e5dSvi sip_copy_header(sip_msg_t sip_msg, sip_header_t sip_header, char *param)
73640cb5e5dSvi {
73740cb5e5dSvi _sip_msg_t *_sip_msg;
73840cb5e5dSvi _sip_header_t *_sip_header;
73940cb5e5dSvi int ret;
74040cb5e5dSvi
74140cb5e5dSvi if (sip_msg == NULL || sip_header == NULL)
74240cb5e5dSvi return (EINVAL);
74340cb5e5dSvi _sip_msg = (_sip_msg_t *)sip_msg;
74440cb5e5dSvi _sip_header = (_sip_header_t *)sip_header;
74540cb5e5dSvi (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
74640cb5e5dSvi if (_sip_msg->sip_msg_cannot_be_modified) {
74740cb5e5dSvi (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
74840cb5e5dSvi return (EPERM);
74940cb5e5dSvi }
75040cb5e5dSvi if (_sip_header->sip_header_state == SIP_HEADER_DELETED) {
75140cb5e5dSvi (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
75240cb5e5dSvi return (EINVAL);
75340cb5e5dSvi }
75440cb5e5dSvi
75540cb5e5dSvi ret = _sip_copy_header(_sip_msg, _sip_header, param, B_TRUE);
75640cb5e5dSvi if (_sip_msg->sip_msg_buf != NULL)
75740cb5e5dSvi _sip_msg->sip_msg_modified = B_TRUE;
75840cb5e5dSvi (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
75940cb5e5dSvi return (ret);
76040cb5e5dSvi }
76140cb5e5dSvi
76240cb5e5dSvi /*
76340cb5e5dSvi * copy the header specified by header_name, with param, if any
76440cb5e5dSvi */
76540cb5e5dSvi int
sip_copy_header_by_name(sip_msg_t old_msg,sip_msg_t new_msg,char * header_name,char * param)76640cb5e5dSvi sip_copy_header_by_name(sip_msg_t old_msg, sip_msg_t new_msg,
76740cb5e5dSvi char *header_name, char *param)
76840cb5e5dSvi {
76940cb5e5dSvi int ret;
77040cb5e5dSvi _sip_msg_t *_old_msg = (_sip_msg_t *)old_msg;
77140cb5e5dSvi _sip_msg_t *_new_msg = (_sip_msg_t *)new_msg;
77240cb5e5dSvi
77340cb5e5dSvi if (_old_msg == NULL || _new_msg == NULL || header_name == NULL ||
77440cb5e5dSvi _old_msg == _new_msg) {
77540cb5e5dSvi return (EINVAL);
77640cb5e5dSvi }
77740cb5e5dSvi (void) pthread_mutex_lock(&_new_msg->sip_msg_mutex);
77840cb5e5dSvi if (_new_msg->sip_msg_cannot_be_modified) {
77940cb5e5dSvi (void) pthread_mutex_unlock(&_new_msg->sip_msg_mutex);
78040cb5e5dSvi return (EPERM);
78140cb5e5dSvi }
78240cb5e5dSvi
78340cb5e5dSvi (void) pthread_mutex_lock(&_old_msg->sip_msg_mutex);
78440cb5e5dSvi ret = _sip_find_and_copy_header(_old_msg, _new_msg, header_name, param,
78540cb5e5dSvi B_FALSE);
78640cb5e5dSvi (void) pthread_mutex_unlock(&_old_msg->sip_msg_mutex);
78740cb5e5dSvi if (_new_msg->sip_msg_buf != NULL)
78840cb5e5dSvi _new_msg->sip_msg_modified = B_TRUE;
78940cb5e5dSvi (void) pthread_mutex_unlock(&_new_msg->sip_msg_mutex);
79040cb5e5dSvi return (ret);
79140cb5e5dSvi }
79240cb5e5dSvi
79340cb5e5dSvi /*
79440cb5e5dSvi * add the given header to sip_message
79540cb5e5dSvi */
79640cb5e5dSvi int
sip_add_header(sip_msg_t sip_msg,char * header_string)79740cb5e5dSvi sip_add_header(sip_msg_t sip_msg, char *header_string)
79840cb5e5dSvi {
79940cb5e5dSvi int header_size;
80040cb5e5dSvi _sip_header_t *new_header;
80140cb5e5dSvi _sip_msg_t *_sip_msg;
80240cb5e5dSvi
80340cb5e5dSvi if (sip_msg == NULL || header_string == NULL)
80440cb5e5dSvi return (EINVAL);
80540cb5e5dSvi _sip_msg = (_sip_msg_t *)sip_msg;
80640cb5e5dSvi (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
80740cb5e5dSvi if (_sip_msg->sip_msg_cannot_be_modified) {
80840cb5e5dSvi (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
80940cb5e5dSvi return (EPERM);
81040cb5e5dSvi }
81140cb5e5dSvi header_size = strlen(header_string) + strlen(SIP_CRLF);
81240cb5e5dSvi new_header = sip_new_header(header_size);
81340cb5e5dSvi if (new_header == NULL) {
81440cb5e5dSvi (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
81540cb5e5dSvi return (ENOMEM);
81640cb5e5dSvi }
81740cb5e5dSvi
81840cb5e5dSvi (void) snprintf(new_header->sip_hdr_start, header_size + 1, "%s%s",
81940cb5e5dSvi header_string, SIP_CRLF);
82040cb5e5dSvi _sip_add_header(_sip_msg, new_header, B_TRUE, B_FALSE, NULL);
82140cb5e5dSvi if (_sip_msg->sip_msg_buf != NULL)
82240cb5e5dSvi _sip_msg->sip_msg_modified = B_TRUE;
82340cb5e5dSvi (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
82440cb5e5dSvi return (0);
82540cb5e5dSvi }
82640cb5e5dSvi
82740cb5e5dSvi /*
82840cb5e5dSvi * add the given param to the sip_header. create a new header with the param
82940cb5e5dSvi * and mark the old header as deleted.
83040cb5e5dSvi */
83140cb5e5dSvi sip_header_t
sip_add_param(sip_header_t sip_header,char * param,int * error)83240cb5e5dSvi sip_add_param(sip_header_t sip_header, char *param, int *error)
83340cb5e5dSvi {
83440cb5e5dSvi _sip_header_t *_sip_header;
83540cb5e5dSvi _sip_header_t *new_header;
83640cb5e5dSvi int hdrlen;
83740cb5e5dSvi _sip_msg_t *_sip_msg;
83840cb5e5dSvi int param_len;
83940cb5e5dSvi char *tmp_ptr;
84040cb5e5dSvi
84140cb5e5dSvi if (error != NULL)
84240cb5e5dSvi *error = 0;
84340cb5e5dSvi
84440cb5e5dSvi if (param == NULL || sip_header == NULL) {
84540cb5e5dSvi if (error != NULL)
84640cb5e5dSvi *error = EINVAL;
84740cb5e5dSvi return (NULL);
84840cb5e5dSvi }
84940cb5e5dSvi
85040cb5e5dSvi _sip_header = (_sip_header_t *)sip_header;
85140cb5e5dSvi
85240cb5e5dSvi (void) pthread_mutex_lock(&_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
85340cb5e5dSvi if (_sip_header->sip_hdr_sipmsg->sip_msg_cannot_be_modified) {
85440cb5e5dSvi if (error != NULL)
85540cb5e5dSvi *error = EPERM;
85640cb5e5dSvi (void) pthread_mutex_unlock(
85740cb5e5dSvi &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
85840cb5e5dSvi return (NULL);
85940cb5e5dSvi }
86040cb5e5dSvi if (_sip_header->sip_header_state == SIP_HEADER_DELETED) {
86140cb5e5dSvi if (error != NULL)
86240cb5e5dSvi *error = EINVAL;
86340cb5e5dSvi (void) pthread_mutex_unlock(
86440cb5e5dSvi &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
86540cb5e5dSvi return (NULL);
86640cb5e5dSvi }
86740cb5e5dSvi
86840cb5e5dSvi param_len = SIP_SPACE_LEN + sizeof (char) + SIP_SPACE_LEN +
86940cb5e5dSvi strlen(param);
87040cb5e5dSvi hdrlen = _sip_header->sip_hdr_end - _sip_header->sip_hdr_start;
87140cb5e5dSvi new_header = sip_new_header(hdrlen + param_len);
87240cb5e5dSvi if (new_header == NULL) {
87340cb5e5dSvi if (error != NULL)
87440cb5e5dSvi *error = ENOMEM;
87540cb5e5dSvi (void) pthread_mutex_unlock(
87640cb5e5dSvi &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
87740cb5e5dSvi return (NULL);
87840cb5e5dSvi }
87940cb5e5dSvi (void) memcpy(new_header->sip_hdr_start, _sip_header->sip_hdr_start,
88040cb5e5dSvi hdrlen);
88140cb5e5dSvi new_header->sip_hdr_end = new_header->sip_hdr_start + hdrlen;
88240cb5e5dSvi hdrlen = param_len + 1;
88340cb5e5dSvi /*
88440cb5e5dSvi * Find CRLF
88540cb5e5dSvi */
88640cb5e5dSvi tmp_ptr = new_header->sip_hdr_end;
88740cb5e5dSvi while (*tmp_ptr-- != '\n') {
88840cb5e5dSvi hdrlen++;
88940cb5e5dSvi if (tmp_ptr == new_header->sip_hdr_start) {
89040cb5e5dSvi sip_free_header(new_header);
89140cb5e5dSvi if (error != NULL)
89240cb5e5dSvi *error = EINVAL;
89340cb5e5dSvi (void) pthread_mutex_unlock(
89440cb5e5dSvi &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
89540cb5e5dSvi return (NULL);
89640cb5e5dSvi }
89740cb5e5dSvi }
89840cb5e5dSvi (void) snprintf(tmp_ptr, hdrlen + 1,
89940cb5e5dSvi " %c %s%s", SIP_SEMI, param, SIP_CRLF);
90040cb5e5dSvi new_header->sip_hdr_end += param_len;
90140cb5e5dSvi new_header->sip_header_functions = _sip_header->sip_header_functions;
90240cb5e5dSvi _sip_msg = _sip_header->sip_hdr_sipmsg;
90340cb5e5dSvi _sip_add_header(_sip_msg, new_header, B_TRUE, B_FALSE, NULL);
90440cb5e5dSvi if (_sip_header->sip_hdr_sipmsg->sip_msg_buf != NULL)
90540cb5e5dSvi _sip_header->sip_hdr_sipmsg->sip_msg_modified = B_TRUE;
90640cb5e5dSvi (void) pthread_mutex_unlock(&new_header->sip_hdr_sipmsg->sip_msg_mutex);
90740cb5e5dSvi (void) sip_delete_header(sip_header);
90840cb5e5dSvi return ((sip_header_t)new_header);
90940cb5e5dSvi }
91040cb5e5dSvi
91140cb5e5dSvi /*
91240cb5e5dSvi * Get Request URI
91340cb5e5dSvi */
91440cb5e5dSvi const struct sip_uri *
sip_get_request_uri(sip_msg_t sip_msg,int * error)91540cb5e5dSvi sip_get_request_uri(sip_msg_t sip_msg, int *error)
91640cb5e5dSvi {
91740cb5e5dSvi _sip_msg_t *_sip_msg;
91840cb5e5dSvi sip_message_type_t *sip_msg_info;
91940cb5e5dSvi const struct sip_uri *ret = NULL;
92040cb5e5dSvi
92140cb5e5dSvi if (error != NULL)
92240cb5e5dSvi *error = 0;
92340cb5e5dSvi
92440cb5e5dSvi if (sip_msg == NULL) {
92540cb5e5dSvi if (error != NULL)
92640cb5e5dSvi *error = EINVAL;
92740cb5e5dSvi return (NULL);
92840cb5e5dSvi }
92940cb5e5dSvi _sip_msg = (_sip_msg_t *)sip_msg;
93040cb5e5dSvi (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
93140cb5e5dSvi sip_msg_info = _sip_msg->sip_msg_req_res;
93240cb5e5dSvi if (sip_msg_info != NULL && sip_msg_info->is_request) {
93340cb5e5dSvi ret = sip_msg_info->sip_req_parse_uri;
93440cb5e5dSvi } else {
93540cb5e5dSvi if (error != NULL)
93640cb5e5dSvi *error = EINVAL;
93740cb5e5dSvi }
93840cb5e5dSvi (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
93940cb5e5dSvi
94040cb5e5dSvi if (ret != NULL) {
94140cb5e5dSvi if (ret->sip_uri_scheme.sip_str_len == 0 ||
94240cb5e5dSvi ret->sip_uri_scheme.sip_str_ptr == NULL) {
94340cb5e5dSvi ret = NULL;
94440cb5e5dSvi if (error != NULL)
94540cb5e5dSvi *error = EINVAL;
94640cb5e5dSvi } else if (ret->sip_uri_errflags != 0 && error != NULL) {
94740cb5e5dSvi *error = EINVAL;
94840cb5e5dSvi }
94940cb5e5dSvi }
95040cb5e5dSvi return ((sip_uri_t)ret);
95140cb5e5dSvi }
95240cb5e5dSvi
95340cb5e5dSvi /*
95440cb5e5dSvi * returns a comma separated string of all the sent-by values registered by
95540cb5e5dSvi * the UA.
95640cb5e5dSvi */
95740cb5e5dSvi char *
sip_sent_by_to_str(int * error)95840cb5e5dSvi sip_sent_by_to_str(int *error)
95940cb5e5dSvi {
96040cb5e5dSvi sent_by_list_t *sb;
96140cb5e5dSvi int sb_len = 0;
96240cb5e5dSvi int slen;
96340cb5e5dSvi char *sb_str;
96440cb5e5dSvi char *p;
96540cb5e5dSvi int count = 0;
96640cb5e5dSvi int cnt = 0;
96740cb5e5dSvi
96840cb5e5dSvi if (error != NULL)
96940cb5e5dSvi *error = 0;
97040cb5e5dSvi
97140cb5e5dSvi (void) pthread_mutex_lock(&sip_sent_by_lock);
97240cb5e5dSvi if (sip_sent_by == NULL) {
97340cb5e5dSvi (void) pthread_mutex_unlock(&sip_sent_by_lock);
97440cb5e5dSvi return (NULL);
97540cb5e5dSvi }
97640cb5e5dSvi sb = sip_sent_by;
97740cb5e5dSvi for (cnt = 0; cnt < sip_sent_by_count; cnt++) {
97840cb5e5dSvi sb_len += strlen(sb->sb_val);
97940cb5e5dSvi sb = sb->sb_next;
98040cb5e5dSvi }
98140cb5e5dSvi /*
98240cb5e5dSvi * for the commas
98340cb5e5dSvi */
98440cb5e5dSvi sb_len += sip_sent_by_count - 1;
98540cb5e5dSvi sb_str = malloc(sb_len + 1);
98640cb5e5dSvi if (sb_str == NULL) {
98740cb5e5dSvi if (error != NULL)
98840cb5e5dSvi *error = ENOMEM;
98940cb5e5dSvi (void) pthread_mutex_unlock(&sip_sent_by_lock);
99040cb5e5dSvi return (NULL);
99140cb5e5dSvi }
99240cb5e5dSvi sb = sip_sent_by;
99340cb5e5dSvi p = sb_str;
99440cb5e5dSvi slen = sb_len + 1;
99540cb5e5dSvi for (cnt = 0; cnt < sip_sent_by_count; cnt++) {
99640cb5e5dSvi if (cnt == 0) {
99740cb5e5dSvi count = snprintf(p, slen, "%s", sb->sb_val);
99840cb5e5dSvi } else {
99940cb5e5dSvi count = snprintf(p, slen, "%c%s", SIP_COMMA,
100040cb5e5dSvi sb->sb_val);
100140cb5e5dSvi }
100240cb5e5dSvi p += count;
100340cb5e5dSvi slen -= count;
100440cb5e5dSvi sb = sb->sb_next;
100540cb5e5dSvi }
100640cb5e5dSvi sb_str[sb_len] = '\0';
100740cb5e5dSvi (void) pthread_mutex_unlock(&sip_sent_by_lock);
100840cb5e5dSvi return (sb_str);
100940cb5e5dSvi }
101040cb5e5dSvi
101140cb5e5dSvi /*
101240cb5e5dSvi * A comma separated list of sent-by values.
101340cb5e5dSvi */
101440cb5e5dSvi int
sip_register_sent_by(char * val)101540cb5e5dSvi sip_register_sent_by(char *val)
101640cb5e5dSvi {
101740cb5e5dSvi sent_by_list_t *sb = NULL;
101840cb5e5dSvi sent_by_list_t *sb_tail = NULL;
101940cb5e5dSvi char *str;
102040cb5e5dSvi int count = 0;
102140cb5e5dSvi
102240cb5e5dSvi if (val == NULL)
102340cb5e5dSvi return (EINVAL);
102440cb5e5dSvi str = strtok(val, ",");
102540cb5e5dSvi while (str != NULL) {
102640cb5e5dSvi int slen;
102740cb5e5dSvi char *start = str;
102840cb5e5dSvi char *end = str + strlen(str) - 1;
102940cb5e5dSvi
103040cb5e5dSvi while (isspace(*start))
103140cb5e5dSvi start++;
103240cb5e5dSvi while (isspace(*end))
103340cb5e5dSvi end--;
103440cb5e5dSvi if (end <= start)
103540cb5e5dSvi goto err_ret;
103640cb5e5dSvi slen = end - start + 1;
103740cb5e5dSvi sb_tail = (sent_by_list_t *)malloc(sizeof (*sb_tail));
103840cb5e5dSvi if (sb_tail == NULL)
103940cb5e5dSvi goto err_ret;
104040cb5e5dSvi sb_tail->sb_next = sb_tail->sb_prev = NULL;
104140cb5e5dSvi if ((sb_tail->sb_val = (char *)malloc(slen + 1)) == NULL) {
104240cb5e5dSvi free(sb_tail);
104340cb5e5dSvi goto err_ret;
104440cb5e5dSvi }
104540cb5e5dSvi (void) strncpy(sb_tail->sb_val, start, slen);
104640cb5e5dSvi sb_tail->sb_val[slen] = '\0';
104740cb5e5dSvi if (sb == NULL) {
104840cb5e5dSvi sb = sb_tail;
104940cb5e5dSvi } else {
105040cb5e5dSvi sb_tail->sb_next = sb;
105140cb5e5dSvi sb->sb_prev = sb_tail;
105240cb5e5dSvi sb = sb_tail;
105340cb5e5dSvi }
105440cb5e5dSvi count++;
105540cb5e5dSvi str = strtok(NULL, ",");
105640cb5e5dSvi }
105740cb5e5dSvi sb_tail = sb;
105840cb5e5dSvi while (sb_tail->sb_next != NULL)
105940cb5e5dSvi sb_tail = sb_tail->sb_next;
106040cb5e5dSvi (void) pthread_mutex_lock(&sip_sent_by_lock);
106140cb5e5dSvi if (sip_sent_by != NULL) {
106240cb5e5dSvi sb_tail->sb_next = sip_sent_by;
106340cb5e5dSvi sip_sent_by->sb_prev = sb_tail;
106440cb5e5dSvi }
106540cb5e5dSvi sip_sent_by = sb;
106640cb5e5dSvi sip_sent_by_count += count;
106740cb5e5dSvi (void) pthread_mutex_unlock(&sip_sent_by_lock);
106840cb5e5dSvi return (0);
106940cb5e5dSvi err_ret:
107040cb5e5dSvi sb_tail = sb;
107140cb5e5dSvi for (; count > 0; count--) {
107240cb5e5dSvi sb = sb_tail->sb_next;
107340cb5e5dSvi free(sb_tail->sb_val);
107440cb5e5dSvi sb_tail->sb_next = NULL;
107540cb5e5dSvi sb_tail->sb_prev = NULL;
107640cb5e5dSvi free(sb_tail);
107740cb5e5dSvi sb_tail = sb;
107840cb5e5dSvi }
107940cb5e5dSvi return (EINVAL);
108040cb5e5dSvi }
108140cb5e5dSvi
108240cb5e5dSvi /*
108340cb5e5dSvi * Un-register sent-by values; 'val' contains a comma separated list
108440cb5e5dSvi */
108540cb5e5dSvi void
sip_unregister_sent_by(char * val)108640cb5e5dSvi sip_unregister_sent_by(char *val)
108740cb5e5dSvi {
108840cb5e5dSvi sent_by_list_t *sb;
108940cb5e5dSvi char *str;
109040cb5e5dSvi int count = 0;
109140cb5e5dSvi
109240cb5e5dSvi (void) pthread_mutex_lock(&sip_sent_by_lock);
109340cb5e5dSvi str = strtok(val, ",");
109440cb5e5dSvi while (str != NULL) {
109540cb5e5dSvi sb = sip_sent_by;
109640cb5e5dSvi for (count = 0; count < sip_sent_by_count; count++) {
109740cb5e5dSvi if (strncmp(sb->sb_val, str, strlen(str)) == 0) {
109840cb5e5dSvi if (sb == sip_sent_by) {
109940cb5e5dSvi if (sb->sb_next != NULL)
110040cb5e5dSvi sip_sent_by = sb->sb_next;
110140cb5e5dSvi else
110240cb5e5dSvi sip_sent_by = NULL;
110340cb5e5dSvi } else if (sb->sb_next == NULL) {
110440cb5e5dSvi sb->sb_prev->sb_next = NULL;
110540cb5e5dSvi } else {
110640cb5e5dSvi sb->sb_prev->sb_next = sb->sb_next;
110740cb5e5dSvi sb->sb_next->sb_prev = sb->sb_prev;
110840cb5e5dSvi }
110940cb5e5dSvi sip_sent_by_count--;
111040cb5e5dSvi sb->sb_next = NULL;
111140cb5e5dSvi sb->sb_prev = NULL;
111240cb5e5dSvi free(sb->sb_val);
111340cb5e5dSvi free(sb);
111440cb5e5dSvi break;
111540cb5e5dSvi }
111640cb5e5dSvi sb = sb->sb_next;
111740cb5e5dSvi }
111840cb5e5dSvi str = strtok(NULL, ",");
111940cb5e5dSvi }
112040cb5e5dSvi (void) pthread_mutex_unlock(&sip_sent_by_lock);
112140cb5e5dSvi }
112240cb5e5dSvi
112340cb5e5dSvi /*
112440cb5e5dSvi * Un-register all the sent-by values
112540cb5e5dSvi */
112640cb5e5dSvi void
sip_unregister_all_sent_by()112740cb5e5dSvi sip_unregister_all_sent_by()
112840cb5e5dSvi {
112940cb5e5dSvi sent_by_list_t *sb;
113040cb5e5dSvi int count;
113140cb5e5dSvi
113240cb5e5dSvi (void) pthread_mutex_lock(&sip_sent_by_lock);
113340cb5e5dSvi sb = sip_sent_by;
113440cb5e5dSvi for (count = 0; count < sip_sent_by_count; count++) {
113540cb5e5dSvi sip_sent_by = sb->sb_next;
113640cb5e5dSvi free(sb->sb_val);
113740cb5e5dSvi sb->sb_next = NULL;
113840cb5e5dSvi sb->sb_prev = NULL;
113940cb5e5dSvi free(sb);
114040cb5e5dSvi sb = sip_sent_by;
114140cb5e5dSvi }
114240cb5e5dSvi sip_sent_by = NULL;
114340cb5e5dSvi sip_sent_by_count = 0;
114440cb5e5dSvi (void) pthread_mutex_unlock(&sip_sent_by_lock);
114540cb5e5dSvi }
114640cb5e5dSvi
114740cb5e5dSvi /*
114840cb5e5dSvi * Given a response code, return the corresponding phrase
114940cb5e5dSvi */
115040cb5e5dSvi char *
sip_get_resp_desc(int resp_code)115140cb5e5dSvi sip_get_resp_desc(int resp_code)
115240cb5e5dSvi {
115340cb5e5dSvi switch (resp_code) {
115440cb5e5dSvi case SIP_TRYING:
115540cb5e5dSvi return ("TRYING");
115640cb5e5dSvi case SIP_RINGING:
115740cb5e5dSvi return ("RINGING");
115840cb5e5dSvi case SIP_CALL_IS_BEING_FORWARDED:
115940cb5e5dSvi return ("CALL_IS_BEING_FORWARDED");
116040cb5e5dSvi case SIP_QUEUED:
116140cb5e5dSvi return ("QUEUED");
116240cb5e5dSvi case SIP_SESSION_PROGRESS:
116340cb5e5dSvi return ("SESSION_PROGRESS");
116440cb5e5dSvi case SIP_OK:
116540cb5e5dSvi return ("OK");
116640cb5e5dSvi case SIP_ACCEPTED:
116740cb5e5dSvi return ("ACCEPTED");
116840cb5e5dSvi case SIP_MULTIPLE_CHOICES:
116940cb5e5dSvi return ("MULTIPLE_CHOICES");
117040cb5e5dSvi case SIP_MOVED_PERMANENTLY:
117140cb5e5dSvi return ("MOVED_PERMANENTLY");
117240cb5e5dSvi case SIP_MOVED_TEMPORARILY:
117340cb5e5dSvi return ("MOVED_TEMPORARILY");
117440cb5e5dSvi case SIP_USE_PROXY:
117540cb5e5dSvi return ("USE_PROXY");
117640cb5e5dSvi case SIP_ALTERNATIVE_SERVICE:
117740cb5e5dSvi return ("ALTERNATIVE_SERVICE");
117840cb5e5dSvi case SIP_BAD_REQUEST:
117940cb5e5dSvi return ("BAD_REQUEST");
118040cb5e5dSvi case SIP_UNAUTHORIZED:
118140cb5e5dSvi return ("UNAUTHORIZED");
118240cb5e5dSvi case SIP_PAYMENT_REQUIRED:
118340cb5e5dSvi return ("PAYMENT_REQUIRED");
118440cb5e5dSvi case SIP_FORBIDDEN:
118540cb5e5dSvi return ("FORBIDDEN");
118640cb5e5dSvi case SIP_NOT_FOUND:
118740cb5e5dSvi return ("NOT_FOUND");
118840cb5e5dSvi case SIP_METHOD_NOT_ALLOWED:
118940cb5e5dSvi return ("METHOD_NOT_ALLOWED");
119040cb5e5dSvi case SIP_NOT_ACCEPTABLE:
119140cb5e5dSvi return ("NOT_ACCEPTABLE");
119240cb5e5dSvi case SIP_PROXY_AUTH_REQUIRED:
119340cb5e5dSvi return ("PROXY_AUTH_REQUIRED");
119440cb5e5dSvi case SIP_REQUEST_TIMEOUT:
119540cb5e5dSvi return ("REQUEST_TIMEOUT");
119640cb5e5dSvi case SIP_GONE:
119740cb5e5dSvi return ("GONE");
119840cb5e5dSvi case SIP_REQUEST_ENTITY_2_LARGE:
119940cb5e5dSvi return ("REQUEST_ENTITY_2_LARGE");
120040cb5e5dSvi case SIP_REQUEST_URI_2_LONG:
120140cb5e5dSvi return ("REQUEST_URI_2_LONG");
120240cb5e5dSvi case SIP_UNSUPPORTED_MEDIA_TYPE:
120340cb5e5dSvi return ("UNSUPPORTED_MEDIA_TYPE");
120440cb5e5dSvi case SIP_UNSUPPORTED_URI_SCHEME:
120540cb5e5dSvi return ("UNSUPPORTED_URI_SCHEME");
120640cb5e5dSvi case SIP_BAD_EXTENSION:
120740cb5e5dSvi return ("BAD_EXTENSION");
120840cb5e5dSvi case SIP_EXTENSION_REQUIRED:
120940cb5e5dSvi return ("EXTENSION_REQUIRED");
121040cb5e5dSvi case SIP_INTERVAL_2_BRIEF:
121140cb5e5dSvi return ("INTERVAL_2_BRIEF");
121240cb5e5dSvi case SIP_TEMPORARILY_UNAVAIL:
121340cb5e5dSvi return ("TEMPORARILY_UNAVAIL");
121440cb5e5dSvi case SIP_CALL_NON_EXISTANT:
121540cb5e5dSvi return ("CALL_NON_EXISTANT");
121640cb5e5dSvi case SIP_LOOP_DETECTED:
121740cb5e5dSvi return ("LOOP_DETECTED");
121840cb5e5dSvi case SIP_TOO_MANY_HOOPS:
121940cb5e5dSvi return ("TOO_MANY_HOOPS");
122040cb5e5dSvi case SIP_ADDRESS_INCOMPLETE:
122140cb5e5dSvi return ("ADDRESS_INCOMPLETE");
122240cb5e5dSvi case SIP_AMBIGUOUS:
122340cb5e5dSvi return ("AMBIGUOUS");
122440cb5e5dSvi case SIP_BUSY_HERE:
122540cb5e5dSvi return ("BUSY_HERE");
122640cb5e5dSvi case SIP_REQUEST_TERMINATED:
122740cb5e5dSvi return ("REQUEST_TERMINATED");
122840cb5e5dSvi case SIP_NOT_ACCEPTABLE_HERE:
122940cb5e5dSvi return ("NOT_ACCEPTABLE_HERE");
123040cb5e5dSvi case SIP_BAD_EVENT:
123140cb5e5dSvi return ("BAD_EVENT");
123240cb5e5dSvi case SIP_REQUEST_PENDING:
123340cb5e5dSvi return ("REQUEST_PENDING");
123440cb5e5dSvi case SIP_UNDECIPHERABLE:
123540cb5e5dSvi return ("UNDECIPHERABLE");
123640cb5e5dSvi case SIP_SERVER_INTERNAL_ERROR:
123740cb5e5dSvi return ("SERVER_INTERNAL_ERROR");
123840cb5e5dSvi case SIP_NOT_IMPLEMENTED:
123940cb5e5dSvi return ("NOT_IMPLEMENTED");
124040cb5e5dSvi case SIP_BAD_GATEWAY:
124140cb5e5dSvi return ("BAD_GATEWAY");
124240cb5e5dSvi case SIP_SERVICE_UNAVAILABLE:
124340cb5e5dSvi return ("SERVICE_UNAVAILABLE");
124440cb5e5dSvi case SIP_SERVER_TIMEOUT:
124540cb5e5dSvi return ("SERVER_TIMEOUT");
124640cb5e5dSvi case SIP_VERSION_NOT_SUPPORTED:
124740cb5e5dSvi return ("VERSION_NOT_SUPPORTED");
124840cb5e5dSvi case SIP_MESSAGE_2_LARGE:
124940cb5e5dSvi return ("MESSAGE_2_LARGE");
125040cb5e5dSvi case SIP_BUSY_EVERYWHERE:
125140cb5e5dSvi return ("BUSY_EVERYWHERE");
125240cb5e5dSvi case SIP_DECLINE:
125340cb5e5dSvi return ("DECLINE");
125440cb5e5dSvi case SIP_DOES_NOT_EXIST_ANYWHERE:
125540cb5e5dSvi return ("DOES_NOT_EXIST_ANYWHERE");
125640cb5e5dSvi case SIP_NOT_ACCEPTABLE_ANYWHERE:
125740cb5e5dSvi return ("NOT_ACCEPTABLE_ANYWHERE");
125840cb5e5dSvi default:
125940cb5e5dSvi return ("UNKNOWN");
126040cb5e5dSvi }
126140cb5e5dSvi }
126240cb5e5dSvi
126340cb5e5dSvi /*
126440cb5e5dSvi * The following three fns initialize and destroy the private library
126540cb5e5dSvi * data in sip_conn_object_t. The assumption is that the 1st member
126640cb5e5dSvi * of sip_conn_object_t is reserved for library use. The private data
126740cb5e5dSvi * is used only for byte-stream protocols such as TCP to accumulate
126840cb5e5dSvi * a complete SIP message, based on the CONTENT-LENGTH value, before
126940cb5e5dSvi * processing it.
127040cb5e5dSvi */
127140cb5e5dSvi int
sip_init_conn_object(sip_conn_object_t obj)127240cb5e5dSvi sip_init_conn_object(sip_conn_object_t obj)
127340cb5e5dSvi {
127440cb5e5dSvi void **obj_val;
127540cb5e5dSvi sip_conn_obj_pvt_t *pvt_data;
127640cb5e5dSvi
127740cb5e5dSvi if (obj == NULL)
127840cb5e5dSvi return (EINVAL);
127940cb5e5dSvi pvt_data = malloc(sizeof (sip_conn_obj_pvt_t));
128040cb5e5dSvi if (pvt_data == NULL)
128140cb5e5dSvi return (ENOMEM);
128240cb5e5dSvi pvt_data->sip_conn_obj_cache = NULL;
128340cb5e5dSvi pvt_data->sip_conn_obj_reass = malloc(sizeof (sip_reass_entry_t));
128440cb5e5dSvi if (pvt_data->sip_conn_obj_reass == NULL) {
128540cb5e5dSvi free(pvt_data);
128640cb5e5dSvi return (ENOMEM);
128740cb5e5dSvi }
128840cb5e5dSvi bzero(pvt_data->sip_conn_obj_reass, sizeof (sip_reass_entry_t));
128940cb5e5dSvi (void) pthread_mutex_init(&pvt_data->sip_conn_obj_reass_lock, NULL);
129040cb5e5dSvi (void) pthread_mutex_init(&pvt_data->sip_conn_obj_cache_lock, NULL);
129140cb5e5dSvi sip_refhold_conn(obj);
129240cb5e5dSvi obj_val = (void *)obj;
129340cb5e5dSvi *obj_val = (void *)pvt_data;
129440cb5e5dSvi
129540cb5e5dSvi return (0);
129640cb5e5dSvi }
129740cb5e5dSvi
129840cb5e5dSvi /*
129940cb5e5dSvi * Clear private date, if any
130040cb5e5dSvi */
130140cb5e5dSvi void
sip_clear_stale_data(sip_conn_object_t obj)130240cb5e5dSvi sip_clear_stale_data(sip_conn_object_t obj)
130340cb5e5dSvi {
130440cb5e5dSvi void **obj_val;
130540cb5e5dSvi sip_conn_obj_pvt_t *pvt_data;
130640cb5e5dSvi sip_reass_entry_t *reass;
130740cb5e5dSvi
130840cb5e5dSvi if (obj == NULL)
130940cb5e5dSvi return;
131040cb5e5dSvi obj_val = (void *)obj;
131140cb5e5dSvi pvt_data = (sip_conn_obj_pvt_t *)*obj_val;
131240cb5e5dSvi (void) pthread_mutex_lock(&pvt_data->sip_conn_obj_reass_lock);
131340cb5e5dSvi reass = pvt_data->sip_conn_obj_reass;
131440cb5e5dSvi if (reass->sip_reass_msg != NULL) {
131540cb5e5dSvi assert(reass->sip_reass_msglen > 0);
131640cb5e5dSvi free(reass->sip_reass_msg);
131740cb5e5dSvi reass->sip_reass_msglen = 0;
131840cb5e5dSvi }
131940cb5e5dSvi assert(reass->sip_reass_msglen == 0);
132040cb5e5dSvi (void) pthread_mutex_unlock(&pvt_data->sip_conn_obj_reass_lock);
132140cb5e5dSvi }
132240cb5e5dSvi
132340cb5e5dSvi /*
132440cb5e5dSvi * Walk through all the transactions, remove if this obj has been cached
132540cb5e5dSvi * by any.
132640cb5e5dSvi */
132740cb5e5dSvi void
sip_conn_destroyed(sip_conn_object_t obj)132840cb5e5dSvi sip_conn_destroyed(sip_conn_object_t obj)
132940cb5e5dSvi {
133040cb5e5dSvi void **obj_val;
133140cb5e5dSvi sip_conn_obj_pvt_t *pvt_data;
133240cb5e5dSvi
133340cb5e5dSvi if (obj == NULL)
133440cb5e5dSvi return;
133540cb5e5dSvi obj_val = (void *)obj;
133640cb5e5dSvi pvt_data = (sip_conn_obj_pvt_t *)*obj_val;
133740cb5e5dSvi
133840cb5e5dSvi sip_clear_stale_data(obj);
133940cb5e5dSvi free(pvt_data->sip_conn_obj_reass);
134040cb5e5dSvi pvt_data->sip_conn_obj_reass = NULL;
134140cb5e5dSvi (void) pthread_mutex_destroy(&pvt_data->sip_conn_obj_reass_lock);
134240cb5e5dSvi
134340cb5e5dSvi sip_del_conn_obj_cache(obj, NULL);
134440cb5e5dSvi (void) pthread_mutex_destroy(&pvt_data->sip_conn_obj_cache_lock);
134540cb5e5dSvi
134640cb5e5dSvi free(pvt_data);
134740cb5e5dSvi *obj_val = NULL;
134840cb5e5dSvi sip_refrele_conn(obj);
134940cb5e5dSvi }
1350