12882Svi117747 /*
22882Svi117747 * CDDL HEADER START
32882Svi117747 *
42882Svi117747 * The contents of this file are subject to the terms of the
52882Svi117747 * Common Development and Distribution License (the "License").
62882Svi117747 * You may not use this file except in compliance with the License.
72882Svi117747 *
82882Svi117747 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
92882Svi117747 * or http://www.opensolaris.org/os/licensing.
102882Svi117747 * See the License for the specific language governing permissions
112882Svi117747 * and limitations under the License.
122882Svi117747 *
132882Svi117747 * When distributing Covered Code, include this CDDL HEADER in each
142882Svi117747 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
152882Svi117747 * If applicable, add the following below this CDDL HEADER, with the
162882Svi117747 * fields enclosed by brackets "[]" replaced with your own identifying
172882Svi117747 * information: Portions Copyright [yyyy] [name of copyright owner]
182882Svi117747 *
192882Svi117747 * CDDL HEADER END
202882Svi117747 */
212882Svi117747
222882Svi117747 /*
23*3439Svi117747 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
242882Svi117747 * Use is subject to license terms.
252882Svi117747 */
262882Svi117747
272882Svi117747 #pragma ident "%Z%%M% %I% %E% SMI"
282882Svi117747
29*3439Svi117747 #include <stdio.h>
30*3439Svi117747 #include <stdlib.h>
31*3439Svi117747 #include <assert.h>
32*3439Svi117747 #include <ctype.h>
33*3439Svi117747 #include <errno.h>
34*3439Svi117747 #include <strings.h>
35*3439Svi117747 #include <pthread.h>
36*3439Svi117747 #include <sip.h>
37*3439Svi117747
382882Svi117747 #include "sip_msg.h"
392882Svi117747 #include "sip_miscdefs.h"
40*3439Svi117747 #include "sip_parse_uri.h"
412882Svi117747 #include "sip_xaction.h"
422882Svi117747
432882Svi117747 #define SIP_BUF_SIZE 128
442882Svi117747
452882Svi117747 /*
462882Svi117747 * Find the header named header, consecutive calls with old_header
472882Svi117747 * passed in will return next header of the same type.
482882Svi117747 * If no name is passed the first header is returned. consectutive calls
492882Svi117747 * with no name but an old header will return the next header.
502882Svi117747 */
512882Svi117747 const struct sip_header *
sip_get_header(sip_msg_t sip_msg,char * header_name,sip_header_t old_header,int * error)522882Svi117747 sip_get_header(sip_msg_t sip_msg, char *header_name, sip_header_t old_header,
532882Svi117747 int *error)
542882Svi117747 {
552882Svi117747 _sip_msg_t *_sip_msg;
562882Svi117747 const struct sip_header *sip_hdr;
572882Svi117747
582882Svi117747 if (error != NULL)
592882Svi117747 *error = 0;
602882Svi117747 if (sip_msg == NULL) {
612882Svi117747 if (error != NULL)
622882Svi117747 *error = EINVAL;
632882Svi117747 return (NULL);
642882Svi117747 }
652882Svi117747 _sip_msg = (_sip_msg_t *)sip_msg;
662882Svi117747 (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
672882Svi117747 sip_hdr = (sip_header_t)sip_search_for_header((_sip_msg_t *)sip_msg,
682882Svi117747 header_name, (_sip_header_t *)old_header);
692882Svi117747 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
702882Svi117747 if (sip_hdr == NULL && error != NULL)
712882Svi117747 *error = EINVAL;
722882Svi117747 return (sip_hdr);
732882Svi117747 }
742882Svi117747
752882Svi117747 /*
762882Svi117747 * Return the request line as a string. Caller releases the returned string.
772882Svi117747 */
782882Svi117747 char *
sip_reqline_to_str(sip_msg_t sip_msg,int * error)792882Svi117747 sip_reqline_to_str(sip_msg_t sip_msg, int *error)
802882Svi117747 {
812882Svi117747 char *reqstr;
822882Svi117747
832882Svi117747 if (error != NULL)
842882Svi117747 *error = 0;
852882Svi117747 if (sip_msg == NULL || !sip_msg_is_request(sip_msg, error)) {
862882Svi117747 if (error != NULL)
872882Svi117747 *error = EINVAL;
882882Svi117747 return (NULL);
892882Svi117747 }
902882Svi117747 reqstr = _sip_startline_to_str((_sip_msg_t *)sip_msg, error);
912882Svi117747 return (reqstr);
922882Svi117747 }
932882Svi117747
942882Svi117747 /*
952882Svi117747 * Return the response line as a string. Caller releases the returned string.
962882Svi117747 */
972882Svi117747 char *
sip_respline_to_str(sip_msg_t sip_msg,int * error)982882Svi117747 sip_respline_to_str(sip_msg_t sip_msg, int *error)
992882Svi117747 {
1002882Svi117747 char *respstr;
1012882Svi117747
1022882Svi117747 if (error != NULL)
1032882Svi117747 *error = 0;
1042882Svi117747 if (sip_msg == NULL || sip_msg_is_request(sip_msg, error)) {
1052882Svi117747 if (error != NULL)
1062882Svi117747 *error = EINVAL;
1072882Svi117747 return (NULL);
1082882Svi117747 }
1092882Svi117747 respstr = _sip_startline_to_str((_sip_msg_t *)sip_msg, error);
1102882Svi117747 return (respstr);
1112882Svi117747 }
1122882Svi117747
1132882Svi117747 /*
1142882Svi117747 * return the first value of the header
1152882Svi117747 */
1162882Svi117747 const struct sip_value *
sip_get_header_value(const struct sip_header * sip_header,int * error)1172882Svi117747 sip_get_header_value(const struct sip_header *sip_header, int *error)
1182882Svi117747 {
1192882Svi117747 _sip_header_t *_sip_header;
1202882Svi117747 sip_parsed_header_t *sip_parsed_header;
1212882Svi117747 int ret = 0;
1222882Svi117747 const struct sip_value *value;
1232882Svi117747
1242882Svi117747 if (error != NULL)
1252882Svi117747 *error = 0;
1262882Svi117747 if (sip_header == NULL) {
1272882Svi117747 if (error != NULL)
1282882Svi117747 *error = EINVAL;
1292882Svi117747 return (NULL);
1302882Svi117747 }
1312882Svi117747 _sip_header = (_sip_header_t *)sip_header;
1322882Svi117747 if (_sip_header->sip_hdr_sipmsg != NULL) {
1332882Svi117747 (void) pthread_mutex_lock(
1342882Svi117747 &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
1352882Svi117747 }
1362882Svi117747 if (_sip_header->sip_header_state == SIP_HEADER_DELETED) {
1372882Svi117747 if (_sip_header->sip_hdr_sipmsg != NULL) {
1382882Svi117747 (void) pthread_mutex_unlock(
1392882Svi117747 &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
1402882Svi117747 }
1412882Svi117747 if (error != NULL)
1422882Svi117747 *error = EINVAL;
1432882Svi117747 return (NULL);
1442882Svi117747 }
1452882Svi117747 ret = _sip_header->sip_header_functions->header_parse_func(
1462882Svi117747 _sip_header, &sip_parsed_header);
1472882Svi117747 if (_sip_header->sip_hdr_sipmsg != NULL) {
1482882Svi117747 (void) pthread_mutex_unlock
1492882Svi117747 (&_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
1502882Svi117747 }
1512882Svi117747 if (error != NULL)
1522882Svi117747 *error = ret;
1532882Svi117747
1542882Svi117747 if (ret != 0)
1552882Svi117747 return (NULL);
1562882Svi117747 value = (sip_header_value_t)sip_parsed_header->value;
1572882Svi117747 while (value != NULL && value->value_state == SIP_VALUE_DELETED)
1582882Svi117747 value = value->next;
1592882Svi117747 if (value != NULL && value->value_state == SIP_VALUE_BAD &&
1602882Svi117747 error != NULL) {
1612882Svi117747 *error = EPROTO;
1622882Svi117747 }
1632882Svi117747 return ((sip_header_value_t)value);
1642882Svi117747 }
1652882Svi117747
1662882Svi117747 /*
1672882Svi117747 * Return the next value of the header.
1682882Svi117747 */
1692882Svi117747 const struct sip_value *
sip_get_next_value(sip_header_value_t old_value,int * error)1702882Svi117747 sip_get_next_value(sip_header_value_t old_value, int *error)
1712882Svi117747 {
1722882Svi117747 const struct sip_value *value;
1732882Svi117747
1742882Svi117747 if (error != NULL)
1752882Svi117747 *error = 0;
1762882Svi117747 if (old_value == NULL || old_value->next == NULL) {
1772882Svi117747 if (error != NULL)
1782882Svi117747 *error = EINVAL;
1792882Svi117747 return (NULL);
1802882Svi117747 }
1812882Svi117747 /*
1822882Svi117747 * We never free the deleted values so no need to hold a lock.
1832882Svi117747 */
1842882Svi117747 value = (sip_header_value_t)old_value->next;
1852882Svi117747 while (value != NULL && value->value_state == SIP_VALUE_DELETED)
1862882Svi117747 value = value->next;
1872882Svi117747 if (value != NULL && value->value_state == SIP_VALUE_BAD &&
1882882Svi117747 error != NULL) {
1892882Svi117747 *error = EPROTO;
1902882Svi117747 }
1912882Svi117747 return ((sip_header_value_t)value);
1922882Svi117747 }
1932882Svi117747
1942882Svi117747 /*
1952882Svi117747 * Given a SIP message, delete the header "header_name".
1962882Svi117747 */
1972882Svi117747 int
sip_delete_header_by_name(sip_msg_t msg,char * header_name)1982882Svi117747 sip_delete_header_by_name(sip_msg_t msg, char *header_name)
1992882Svi117747 {
2002882Svi117747 _sip_msg_t *_msg = (_sip_msg_t *)msg;
2012882Svi117747 sip_header_t sip_hdr;
2022882Svi117747 _sip_header_t *_sip_hdr;
2032882Svi117747
2042882Svi117747 if (_msg == NULL || header_name == NULL)
2052882Svi117747 return (EINVAL);
2062882Svi117747 (void) pthread_mutex_lock(&_msg->sip_msg_mutex);
2072882Svi117747 if (_msg->sip_msg_cannot_be_modified) {
2082882Svi117747 (void) pthread_mutex_unlock(&_msg->sip_msg_mutex);
2092882Svi117747 return (EPERM);
2102882Svi117747 }
2112882Svi117747 sip_hdr = (sip_header_t)sip_search_for_header(_msg, header_name, NULL);
2122882Svi117747 if (sip_hdr == NULL) {
2132882Svi117747 (void) pthread_mutex_unlock(&_msg->sip_msg_mutex);
2142882Svi117747 return (EINVAL);
2152882Svi117747 }
2162882Svi117747 _sip_hdr = (_sip_header_t *)sip_hdr;
2172882Svi117747 _sip_hdr->sip_header_state = SIP_HEADER_DELETED;
2182882Svi117747 _sip_hdr->sip_hdr_sipmsg->sip_msg_len -= _sip_hdr->sip_hdr_end -
2192882Svi117747 _sip_hdr->sip_hdr_start;
2202882Svi117747 assert(_sip_hdr->sip_hdr_sipmsg->sip_msg_len >= 0);
2212882Svi117747 if (_msg->sip_msg_buf != NULL)
2222882Svi117747 _msg->sip_msg_modified = B_TRUE;
2232882Svi117747 (void) pthread_mutex_unlock(&_msg->sip_msg_mutex);
2242882Svi117747
2252882Svi117747 return (0);
2262882Svi117747 }
2272882Svi117747
2282882Svi117747 /*
2292882Svi117747 * Mark the header as deleted.
2302882Svi117747 */
2312882Svi117747 int
sip_delete_header(sip_header_t sip_header)2322882Svi117747 sip_delete_header(sip_header_t sip_header)
2332882Svi117747 {
2342882Svi117747 _sip_header_t *_sip_header;
2352882Svi117747
2362882Svi117747 if (sip_header == NULL)
2372882Svi117747 return (EINVAL);
2382882Svi117747 _sip_header = (_sip_header_t *)sip_header;
2392882Svi117747 (void) pthread_mutex_lock(&_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
2402882Svi117747 if (_sip_header->sip_hdr_sipmsg->sip_msg_cannot_be_modified) {
2412882Svi117747 (void) pthread_mutex_unlock
2422882Svi117747 (&_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
2432882Svi117747 return (EPERM);
2442882Svi117747 }
2452882Svi117747 if (_sip_header->sip_header_state == SIP_HEADER_DELETED) {
2462882Svi117747 (void) pthread_mutex_unlock(
2472882Svi117747 &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
2482882Svi117747 return (EINVAL);
2492882Svi117747 }
2502882Svi117747 _sip_header->sip_header_state = SIP_HEADER_DELETED;
2512882Svi117747 _sip_header->sip_hdr_sipmsg->sip_msg_len -= _sip_header->sip_hdr_end -
2522882Svi117747 _sip_header->sip_hdr_start;
2532882Svi117747 assert(_sip_header->sip_hdr_sipmsg->sip_msg_len >= 0);
2542882Svi117747 if (_sip_header->sip_hdr_sipmsg->sip_msg_buf != NULL)
2552882Svi117747 _sip_header->sip_hdr_sipmsg->sip_msg_modified = B_TRUE;
2562882Svi117747 (void) pthread_mutex_unlock
2572882Svi117747 (&_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
2582882Svi117747 return (0);
2592882Svi117747 }
2602882Svi117747
2612882Svi117747 /*
2622882Svi117747 * Mark the value as deleted.
2632882Svi117747 */
2642882Svi117747 int
sip_delete_value(sip_header_t sip_header,sip_header_value_t sip_header_value)2652882Svi117747 sip_delete_value(sip_header_t sip_header, sip_header_value_t sip_header_value)
2662882Svi117747 {
2672882Svi117747 _sip_header_t *_sip_header;
2682882Svi117747 sip_value_t *_sip_header_value;
2692882Svi117747 int vlen;
2702882Svi117747 char *c;
2712882Svi117747
2722882Svi117747 if (sip_header == NULL || sip_header_value == NULL)
2732882Svi117747 return (EINVAL);
2742882Svi117747 _sip_header = (_sip_header_t *)sip_header;
2752882Svi117747 (void) pthread_mutex_lock(&_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
2762882Svi117747 if (_sip_header->sip_hdr_sipmsg->sip_msg_cannot_be_modified) {
2772882Svi117747 (void) pthread_mutex_unlock(&_sip_header->
2782882Svi117747 sip_hdr_sipmsg->sip_msg_mutex);
2792882Svi117747 return (EPERM);
2802882Svi117747 }
2812882Svi117747 if (_sip_header->sip_header_state == SIP_HEADER_DELETED) {
2822882Svi117747 (void) pthread_mutex_unlock(
2832882Svi117747 &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
2842882Svi117747 return (EINVAL);
2852882Svi117747 }
2862882Svi117747 _sip_header_value = (sip_value_t *)sip_header_value;
2872882Svi117747 if (_sip_header_value->value_state == SIP_VALUE_DELETED) {
2882882Svi117747 (void) pthread_mutex_unlock(
2892882Svi117747 &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
2902882Svi117747 return (EINVAL);
2912882Svi117747 }
2922882Svi117747 _sip_header->sip_header_state = SIP_HEADER_DELETED_VAL;
2932882Svi117747 _sip_header_value->value_state = SIP_VALUE_DELETED;
2942882Svi117747 vlen = _sip_header_value->value_end - _sip_header_value->value_start;
2952882Svi117747 if (_sip_header->sip_hdr_parsed->value == _sip_header_value) {
2962882Svi117747 c = _sip_header_value->value_start;
2972882Svi117747 while (*c-- != SIP_HCOLON)
2982882Svi117747 vlen++;
2992882Svi117747 } else {
3002882Svi117747 c = _sip_header_value->value_start;
3012882Svi117747 while (*c-- != SIP_COMMA)
3022882Svi117747 vlen++;
3032882Svi117747 }
3042882Svi117747 if (_sip_header_value->next == NULL) {
3052882Svi117747 sip_value_t *value = _sip_header->sip_hdr_parsed->value;
3062882Svi117747 boolean_t crlf_present = B_FALSE;
3072882Svi117747 char *s;
3082882Svi117747
3092882Svi117747 while (value != NULL && value != _sip_header_value) {
3102882Svi117747 crlf_present = B_FALSE;
3112882Svi117747
3122882Svi117747 if (value->value_state == SIP_VALUE_DELETED) {
3132882Svi117747 value = value->next;
3142882Svi117747 continue;
3152882Svi117747 }
3162882Svi117747 s = value->value_end;
3172882Svi117747 while (s != value->value_start) {
3182882Svi117747 if (*s == '\r' && strncmp(s, SIP_CRLF,
3192882Svi117747 strlen(SIP_CRLF)) == 0) {
3202882Svi117747 crlf_present = B_TRUE;
3212882Svi117747 break;
3222882Svi117747 }
3232882Svi117747 s--;
3242882Svi117747 }
3252882Svi117747 value = value->next;
3262882Svi117747 }
3272882Svi117747 if (!crlf_present) {
3282882Svi117747 c = _sip_header_value->value_end;
3292882Svi117747 while (*c-- != '\r')
3302882Svi117747 vlen--;
3312882Svi117747 assert(vlen > 0);
3322882Svi117747 }
3332882Svi117747 }
3342882Svi117747 _sip_header->sip_hdr_sipmsg->sip_msg_len -= vlen;
3352882Svi117747 if (_sip_header->sip_hdr_sipmsg->sip_msg_buf != NULL)
3362882Svi117747 _sip_header->sip_hdr_sipmsg->sip_msg_modified = B_TRUE;
3372882Svi117747 (void) pthread_mutex_unlock
3382882Svi117747 (&_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
3392882Svi117747 return (0);
3402882Svi117747 }
3412882Svi117747
3422882Svi117747 /*
3432882Svi117747 * Given a param list, check if a param name exists.
3442882Svi117747 */
3452882Svi117747 boolean_t
sip_is_param_present(const sip_param_t * param_list,char * param_name,int param_len)3462882Svi117747 sip_is_param_present(const sip_param_t *param_list, char *param_name,
3472882Svi117747 int param_len)
3482882Svi117747 {
3492882Svi117747 const sip_param_t *param = param_list;
3502882Svi117747
3512882Svi117747 while (param != NULL) {
3522882Svi117747 if (param->param_name.sip_str_len == param_len &&
3532882Svi117747 strncasecmp(param->param_name.sip_str_ptr, param_name,
3542882Svi117747 param_len) == 0) {
3552882Svi117747 return (B_TRUE);
3562882Svi117747 }
3572882Svi117747 param = param->param_next;
3582882Svi117747 }
3592882Svi117747 return (B_FALSE);
3602882Svi117747 }
3612882Svi117747
3622882Svi117747
3632882Svi117747 /*
3642882Svi117747 * Given a value header return the value of the named param.
3652882Svi117747 */
3662882Svi117747 const sip_str_t *
sip_get_param_value(sip_header_value_t header_value,char * param_name,int * error)3672882Svi117747 sip_get_param_value(sip_header_value_t header_value, char *param_name,
3682882Svi117747 int *error)
3692882Svi117747 {
3702882Svi117747 sip_value_t *_sip_header_value;
3712882Svi117747 sip_param_t *sip_param;
3722882Svi117747
3732882Svi117747 if (error != NULL)
3742882Svi117747 *error = 0;
3752882Svi117747 if (header_value == NULL || param_name == NULL) {
3762882Svi117747 if (error != NULL)
3772882Svi117747 *error = EINVAL;
3782882Svi117747 return (NULL);
3792882Svi117747 }
3802882Svi117747 _sip_header_value = (sip_value_t *)header_value;
3812882Svi117747 if (_sip_header_value->value_state == SIP_VALUE_DELETED) {
3822882Svi117747 if (error != NULL)
3832882Svi117747 *error = EINVAL;
3842882Svi117747 return (NULL);
3852882Svi117747 }
3862882Svi117747 if (_sip_header_value->param_list == NULL) {
3872882Svi117747 if (error != NULL)
3882882Svi117747 *error = EINVAL;
3892882Svi117747 return (NULL);
3902882Svi117747 }
3912882Svi117747 sip_param = sip_get_param_from_list(_sip_header_value->param_list,
3922882Svi117747 param_name);
3932882Svi117747 if (sip_param != NULL)
3942882Svi117747 return (&sip_param->param_value);
3952882Svi117747 return (NULL);
3962882Svi117747 }
3972882Svi117747
3982882Svi117747 /*
3992882Svi117747 * Return the list of params in the header
4002882Svi117747 */
4012882Svi117747 const sip_param_t *
sip_get_params(sip_header_value_t header_value,int * error)4022882Svi117747 sip_get_params(sip_header_value_t header_value, int *error)
4032882Svi117747 {
4042882Svi117747 sip_value_t *sip_header_value;
4052882Svi117747
4062882Svi117747 if (error != NULL)
4072882Svi117747 *error = 0;
4082882Svi117747 if (header_value == NULL) {
4092882Svi117747 if (error != NULL)
4102882Svi117747 *error = EINVAL;
4112882Svi117747 return (NULL);
4122882Svi117747 }
4132882Svi117747 sip_header_value = (sip_value_t *)header_value;
4142882Svi117747 if (sip_header_value->value_state == SIP_VALUE_DELETED) {
4152882Svi117747 if (error != NULL)
4162882Svi117747 *error = EINVAL;
4172882Svi117747 return (NULL);
4182882Svi117747 }
4192882Svi117747 return (sip_header_value->param_list);
4202882Svi117747 }
4212882Svi117747
4222882Svi117747 /*
4232882Svi117747 * Return true if this is a SIP request
4242882Svi117747 */
4252882Svi117747 boolean_t
sip_msg_is_request(sip_msg_t sip_msg,int * error)4262882Svi117747 sip_msg_is_request(sip_msg_t sip_msg, int *error)
4272882Svi117747 {
4282882Svi117747 _sip_msg_t *_sip_msg;
4292882Svi117747 sip_message_type_t *sip_msg_info;
4302882Svi117747 boolean_t ret;
4312882Svi117747
4322882Svi117747 if (error != NULL)
4332882Svi117747 *error = 0;
4342882Svi117747 if (sip_msg == NULL) {
4352882Svi117747 if (error != NULL)
4362882Svi117747 *error = EINVAL;
4372882Svi117747 return (B_FALSE);
4382882Svi117747 }
4392882Svi117747 _sip_msg = (_sip_msg_t *)sip_msg;
4402882Svi117747 (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
4412882Svi117747 if (_sip_msg->sip_msg_req_res == NULL) {
4422882Svi117747 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
4432882Svi117747 if (error != NULL)
4442882Svi117747 *error = EINVAL;
4452882Svi117747 return (B_FALSE);
4462882Svi117747 }
4472882Svi117747 sip_msg_info = _sip_msg->sip_msg_req_res;
4482882Svi117747 ret = sip_msg_info->is_request;
4492882Svi117747 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
4502882Svi117747 return (ret);
4512882Svi117747 }
4522882Svi117747
4532882Svi117747 /*
4542882Svi117747 * Return true if this is a SIP response
4552882Svi117747 */
4562882Svi117747 boolean_t
sip_msg_is_response(sip_msg_t sip_msg,int * error)4572882Svi117747 sip_msg_is_response(sip_msg_t sip_msg, int *error)
4582882Svi117747 {
4592882Svi117747 boolean_t is_resp;
4602882Svi117747 _sip_msg_t *_sip_msg;
4612882Svi117747 sip_message_type_t *sip_msg_info;
4622882Svi117747
4632882Svi117747 if (error != NULL)
4642882Svi117747 *error = 0;
4652882Svi117747 if (sip_msg == NULL) {
4662882Svi117747 if (error != NULL)
4672882Svi117747 *error = EINVAL;
4682882Svi117747 return (B_FALSE);
4692882Svi117747 }
4702882Svi117747 _sip_msg = (_sip_msg_t *)sip_msg;
4712882Svi117747 (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
4722882Svi117747 if (_sip_msg->sip_msg_req_res == NULL) {
4732882Svi117747 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
4742882Svi117747 if (error != NULL)
4752882Svi117747 *error = EINVAL;
4762882Svi117747 return (B_FALSE);
4772882Svi117747 }
4782882Svi117747 sip_msg_info = _sip_msg->sip_msg_req_res;
4792882Svi117747 is_resp = !sip_msg_info->is_request;
4802882Svi117747 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
4812882Svi117747 return (is_resp);
4822882Svi117747 }
4832882Svi117747
4842882Svi117747 /*
4852882Svi117747 * Return the method in the request line
4862882Svi117747 */
4872882Svi117747 sip_method_t
sip_get_request_method(sip_msg_t sip_msg,int * error)4882882Svi117747 sip_get_request_method(sip_msg_t sip_msg, int *error)
4892882Svi117747 {
4902882Svi117747 _sip_msg_t *_sip_msg;
4912882Svi117747 sip_message_type_t *sip_msg_info;
4922882Svi117747 sip_method_t ret = -1;
4932882Svi117747
4942882Svi117747 if (error != NULL)
4952882Svi117747 *error = 0;
4962882Svi117747 if (sip_msg == NULL) {
4972882Svi117747 if (error != NULL)
4982882Svi117747 *error = EINVAL;
4992882Svi117747 return (ret);
5002882Svi117747 }
5012882Svi117747 _sip_msg = (_sip_msg_t *)sip_msg;
5022882Svi117747 (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
5032882Svi117747 sip_msg_info = _sip_msg->sip_msg_req_res;
5042882Svi117747 if (_sip_msg->sip_msg_req_res == NULL) {
5052882Svi117747 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
5062882Svi117747 if (error != NULL)
5072882Svi117747 *error = EINVAL;
5082882Svi117747 return (ret);
5092882Svi117747 }
5102882Svi117747 if (sip_msg_info->is_request)
5112882Svi117747 ret = sip_msg_info->sip_req_method;
5122882Svi117747 else if (error != NULL)
5132882Svi117747 *error = EINVAL;
5142882Svi117747 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
5152882Svi117747 return (ret);
5162882Svi117747 }
5172882Svi117747
5182882Svi117747 /*
5192882Svi117747 * Return the URI from the request line
5202882Svi117747 */
5212882Svi117747 const sip_str_t *
sip_get_request_uri_str(sip_msg_t sip_msg,int * error)5222882Svi117747 sip_get_request_uri_str(sip_msg_t sip_msg, int *error)
5232882Svi117747 {
5242882Svi117747 _sip_msg_t *_sip_msg;
5252882Svi117747 sip_message_type_t *sip_msg_info;
5262882Svi117747 sip_str_t *ret = NULL;
5272882Svi117747 struct sip_uri *parsed_uri;
5282882Svi117747
5292882Svi117747 if (error != NULL)
5302882Svi117747 *error = 0;
5312882Svi117747 if (sip_msg == NULL) {
5322882Svi117747 if (error != NULL)
5332882Svi117747 *error = EINVAL;
5342882Svi117747 return (NULL);
5352882Svi117747 }
5362882Svi117747 _sip_msg = (_sip_msg_t *)sip_msg;
5372882Svi117747 (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
5382882Svi117747 if (_sip_msg->sip_msg_req_res == NULL) {
5392882Svi117747 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
5402882Svi117747 if (error != NULL)
5412882Svi117747 *error = EINVAL;
5422882Svi117747 return (NULL);
5432882Svi117747 }
5442882Svi117747 sip_msg_info = _sip_msg->sip_msg_req_res;
5452882Svi117747 if (sip_msg_info->is_request)
5462882Svi117747 ret = &sip_msg_info->sip_req_uri;
5472882Svi117747 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
5482882Svi117747
5492882Svi117747 /*
5502882Svi117747 * If the error is required, check the validity of the URI via
5512882Svi117747 * sip_uri_parse().
5522882Svi117747 */
5532882Svi117747 if (error != NULL) {
5542882Svi117747 parsed_uri = sip_parse_uri(ret, error);
5552882Svi117747 if (parsed_uri != NULL)
5562882Svi117747 sip_free_parsed_uri((sip_uri_t)parsed_uri);
5572882Svi117747 }
5582882Svi117747 return (ret);
5592882Svi117747 }
5602882Svi117747
5612882Svi117747 /*
5622882Svi117747 * Return the response code
5632882Svi117747 */
5642882Svi117747 int
sip_get_response_code(sip_msg_t sip_msg,int * error)5652882Svi117747 sip_get_response_code(sip_msg_t sip_msg, int *error)
5662882Svi117747 {
5672882Svi117747 _sip_msg_t *_sip_msg;
5682882Svi117747 sip_message_type_t *sip_msg_info;
5692882Svi117747 int ret = -1;
5702882Svi117747
5712882Svi117747 if (error != NULL)
5722882Svi117747 *error = 0;
5732882Svi117747 if (sip_msg == NULL) {
5742882Svi117747 if (error != NULL)
5752882Svi117747 *error = EINVAL;
5762882Svi117747 return (ret);
5772882Svi117747 }
5782882Svi117747 _sip_msg = (_sip_msg_t *)sip_msg;
5792882Svi117747 (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
5802882Svi117747 if (_sip_msg->sip_msg_req_res == NULL) {
5812882Svi117747 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
5822882Svi117747 if (error != NULL)
5832882Svi117747 *error = EINVAL;
5842882Svi117747 return (ret);
5852882Svi117747 }
5862882Svi117747 sip_msg_info = _sip_msg->sip_msg_req_res;
5872882Svi117747 if (!sip_msg_info->is_request)
5882882Svi117747 ret = sip_msg_info->sip_resp_code;
5892882Svi117747 else if (error != NULL)
5902882Svi117747 *error = EINVAL;
5912882Svi117747 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
5922882Svi117747 return (ret);
5932882Svi117747 }
5942882Svi117747
5952882Svi117747 /*
5962882Svi117747 * Get the response phrase
5972882Svi117747 */
5982882Svi117747 const sip_str_t *
sip_get_response_phrase(sip_msg_t sip_msg,int * error)5992882Svi117747 sip_get_response_phrase(sip_msg_t sip_msg, int *error)
6002882Svi117747 {
6012882Svi117747 _sip_msg_t *_sip_msg;
6022882Svi117747 sip_message_type_t *sip_msg_info;
6032882Svi117747 sip_str_t *ret = NULL;
6042882Svi117747
6052882Svi117747 if (error != NULL)
6062882Svi117747 *error = 0;
6072882Svi117747 if (sip_msg == NULL) {
6082882Svi117747 if (error != NULL)
6092882Svi117747 *error = EINVAL;
6102882Svi117747 return (ret);
6112882Svi117747 }
6122882Svi117747 _sip_msg = (_sip_msg_t *)sip_msg;
6132882Svi117747 (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
6142882Svi117747 if (_sip_msg->sip_msg_req_res == NULL) {
6152882Svi117747 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
6162882Svi117747 if (error != NULL)
6172882Svi117747 *error = EINVAL;
6182882Svi117747 return (ret);
6192882Svi117747 }
6202882Svi117747 sip_msg_info = _sip_msg->sip_msg_req_res;
6212882Svi117747 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
6222882Svi117747 if (!sip_msg_info->is_request) {
6232882Svi117747 if (sip_msg_info->sip_resp_phrase_len == 0)
6242882Svi117747 ret = NULL;
6252882Svi117747 else
6262882Svi117747 ret = &sip_msg_info->sip_resp_phrase;
6272882Svi117747 } else if (error != NULL) {
6282882Svi117747 *error = EINVAL;
6292882Svi117747 }
6302882Svi117747 return (ret);
6312882Svi117747 }
6322882Svi117747
6332882Svi117747 /*
6342882Svi117747 * Get the SIP version string
6352882Svi117747 */
6362882Svi117747 const sip_str_t *
sip_get_sip_version(sip_msg_t sip_msg,int * error)6372882Svi117747 sip_get_sip_version(sip_msg_t sip_msg, int *error)
6382882Svi117747 {
6392882Svi117747 _sip_msg_t *_sip_msg;
6402882Svi117747 sip_message_type_t *sip_msg_info;
6412882Svi117747 sip_str_t *ret = NULL;
6422882Svi117747
6432882Svi117747 if (error != NULL)
6442882Svi117747 *error = 0;
6452882Svi117747 if (sip_msg == NULL) {
6462882Svi117747 if (error != NULL)
6472882Svi117747 *error = EINVAL;
6482882Svi117747 return (ret);
6492882Svi117747 }
6502882Svi117747 _sip_msg = (_sip_msg_t *)sip_msg;
6512882Svi117747 (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
6522882Svi117747 if (_sip_msg->sip_msg_req_res == NULL) {
6532882Svi117747 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
6542882Svi117747 if (error != NULL)
6552882Svi117747 *error = EINVAL;
6562882Svi117747 return (ret);
6572882Svi117747 }
6582882Svi117747 sip_msg_info = _sip_msg->sip_msg_req_res;
6592882Svi117747 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
6602882Svi117747 ret = &sip_msg_info->sip_proto_version.version;
6612882Svi117747 return (ret);
6622882Svi117747 }
6632882Svi117747
6642882Svi117747 /*
6652882Svi117747 * Return the length of the SIP message
6662882Svi117747 */
6672882Svi117747 int
sip_get_msg_len(sip_msg_t sip_msg,int * error)6682882Svi117747 sip_get_msg_len(sip_msg_t sip_msg, int *error)
6692882Svi117747 {
6702882Svi117747 _sip_msg_t *_sip_msg;
6712882Svi117747
6722882Svi117747 if (error != NULL)
6732882Svi117747 *error = 0;
6742882Svi117747 if (sip_msg == NULL) {
6752882Svi117747 if (error != NULL)
6762882Svi117747 *error = EINVAL;
6772882Svi117747 return (-1);
6782882Svi117747 }
6792882Svi117747 _sip_msg = (_sip_msg_t *)sip_msg;
6802882Svi117747
6812882Svi117747 return (_sip_msg->sip_msg_len);
6822882Svi117747 }
6832882Svi117747
6842882Svi117747 /*
6852882Svi117747 * Get content as a string. Caller frees the string
6862882Svi117747 */
6872882Svi117747 char *
sip_get_content(sip_msg_t sip_msg,int * error)6882882Svi117747 sip_get_content(sip_msg_t sip_msg, int *error)
6892882Svi117747 {
6902882Svi117747 _sip_msg_t *_sip_msg;
6912882Svi117747 sip_content_t *sip_content;
6922882Svi117747 char *content;
6932882Svi117747 int len;
6942882Svi117747 char *p;
6952882Svi117747
6962882Svi117747 if (error != NULL)
6972882Svi117747 *error = 0;
6982882Svi117747
6992882Svi117747 if (sip_msg == NULL) {
7002882Svi117747 if (error != NULL)
7012882Svi117747 *error = EINVAL;
7022882Svi117747 return (NULL);
7032882Svi117747 }
7042882Svi117747 _sip_msg = (_sip_msg_t *)sip_msg;
7052882Svi117747 (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
7062882Svi117747 if (_sip_msg->sip_msg_content == NULL) {
7072882Svi117747 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
7082882Svi117747 if (error != NULL)
7092882Svi117747 *error = EINVAL;
7102882Svi117747 return (NULL);
7112882Svi117747 }
7122882Svi117747 content = malloc(_sip_msg->sip_msg_content_len + 1);
7132882Svi117747 if (content == NULL) {
7142882Svi117747 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
7152882Svi117747 if (error != NULL)
7162882Svi117747 *error = ENOMEM;
7172882Svi117747 return (NULL);
7182882Svi117747 }
7192882Svi117747 p = content;
7202882Svi117747 sip_content = _sip_msg->sip_msg_content;
7212882Svi117747 while (sip_content != NULL) {
7222882Svi117747 len = sip_content->sip_content_end -
7232882Svi117747 sip_content->sip_content_start;
7242882Svi117747 (void) strncpy(p, sip_content->sip_content_start, len);
7252882Svi117747 p += len;
7262882Svi117747 sip_content = sip_content->sip_content_next;
7272882Svi117747 }
7282882Svi117747 content[_sip_msg->sip_msg_content_len] = '\0';
7292882Svi117747 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
7302882Svi117747 return (content);
7312882Svi117747 }
7322882Svi117747
7332882Svi117747 /*
7342882Svi117747 * copy sip_header with param, if any, to sip_msg
7352882Svi117747 */
7362882Svi117747 int
sip_copy_header(sip_msg_t sip_msg,sip_header_t sip_header,char * param)7372882Svi117747 sip_copy_header(sip_msg_t sip_msg, sip_header_t sip_header, char *param)
7382882Svi117747 {
7392882Svi117747 _sip_msg_t *_sip_msg;
7402882Svi117747 _sip_header_t *_sip_header;
7412882Svi117747 int ret;
7422882Svi117747
7432882Svi117747 if (sip_msg == NULL || sip_header == NULL)
7442882Svi117747 return (EINVAL);
7452882Svi117747 _sip_msg = (_sip_msg_t *)sip_msg;
7462882Svi117747 _sip_header = (_sip_header_t *)sip_header;
7472882Svi117747 (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
7482882Svi117747 if (_sip_msg->sip_msg_cannot_be_modified) {
7492882Svi117747 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
7502882Svi117747 return (EPERM);
7512882Svi117747 }
7522882Svi117747 if (_sip_header->sip_header_state == SIP_HEADER_DELETED) {
7532882Svi117747 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
7542882Svi117747 return (EINVAL);
7552882Svi117747 }
7562882Svi117747
7572882Svi117747 ret = _sip_copy_header(_sip_msg, _sip_header, param, B_TRUE);
7582882Svi117747 if (_sip_msg->sip_msg_buf != NULL)
7592882Svi117747 _sip_msg->sip_msg_modified = B_TRUE;
7602882Svi117747 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
7612882Svi117747 return (ret);
7622882Svi117747 }
7632882Svi117747
7642882Svi117747 /*
7652882Svi117747 * copy the header specified by header_name, with param, if any
7662882Svi117747 */
7672882Svi117747 int
sip_copy_header_by_name(sip_msg_t old_msg,sip_msg_t new_msg,char * header_name,char * param)7682882Svi117747 sip_copy_header_by_name(sip_msg_t old_msg, sip_msg_t new_msg,
7692882Svi117747 char *header_name, char *param)
7702882Svi117747 {
7712882Svi117747 int ret;
7722882Svi117747 _sip_msg_t *_old_msg = (_sip_msg_t *)old_msg;
7732882Svi117747 _sip_msg_t *_new_msg = (_sip_msg_t *)new_msg;
7742882Svi117747
7752882Svi117747 if (_old_msg == NULL || _new_msg == NULL || header_name == NULL ||
7762882Svi117747 _old_msg == _new_msg) {
7772882Svi117747 return (EINVAL);
7782882Svi117747 }
7792882Svi117747 (void) pthread_mutex_lock(&_new_msg->sip_msg_mutex);
7802882Svi117747 if (_new_msg->sip_msg_cannot_be_modified) {
7812882Svi117747 (void) pthread_mutex_unlock(&_new_msg->sip_msg_mutex);
7822882Svi117747 return (EPERM);
7832882Svi117747 }
7842882Svi117747
7852882Svi117747 (void) pthread_mutex_lock(&_old_msg->sip_msg_mutex);
7862882Svi117747 ret = _sip_find_and_copy_header(_old_msg, _new_msg, header_name, param,
7872882Svi117747 B_FALSE);
7882882Svi117747 (void) pthread_mutex_unlock(&_old_msg->sip_msg_mutex);
7892882Svi117747 if (_new_msg->sip_msg_buf != NULL)
7902882Svi117747 _new_msg->sip_msg_modified = B_TRUE;
7912882Svi117747 (void) pthread_mutex_unlock(&_new_msg->sip_msg_mutex);
7922882Svi117747 return (ret);
7932882Svi117747 }
7942882Svi117747
7952882Svi117747 /*
7962882Svi117747 * add the given header to sip_message
7972882Svi117747 */
7982882Svi117747 int
sip_add_header(sip_msg_t sip_msg,char * header_string)7992882Svi117747 sip_add_header(sip_msg_t sip_msg, char *header_string)
8002882Svi117747 {
8012882Svi117747 int header_size;
8022882Svi117747 _sip_header_t *new_header;
8032882Svi117747 _sip_msg_t *_sip_msg;
8042882Svi117747
8052882Svi117747 if (sip_msg == NULL || header_string == NULL)
8062882Svi117747 return (EINVAL);
8072882Svi117747 _sip_msg = (_sip_msg_t *)sip_msg;
8082882Svi117747 (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
8092882Svi117747 if (_sip_msg->sip_msg_cannot_be_modified) {
8102882Svi117747 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
8112882Svi117747 return (EPERM);
8122882Svi117747 }
8132882Svi117747 header_size = strlen(header_string) + strlen(SIP_CRLF);
8142882Svi117747 new_header = sip_new_header(header_size);
8152882Svi117747 if (new_header == NULL) {
8162882Svi117747 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
8172882Svi117747 return (ENOMEM);
8182882Svi117747 }
8192882Svi117747
8202882Svi117747 (void) snprintf(new_header->sip_hdr_start, header_size + 1, "%s%s",
8212882Svi117747 header_string, SIP_CRLF);
8222882Svi117747 _sip_add_header(_sip_msg, new_header, B_TRUE, B_FALSE, NULL);
8232882Svi117747 if (_sip_msg->sip_msg_buf != NULL)
8242882Svi117747 _sip_msg->sip_msg_modified = B_TRUE;
8252882Svi117747 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
8262882Svi117747 return (0);
8272882Svi117747 }
8282882Svi117747
8292882Svi117747 /*
8302882Svi117747 * add the given param to the sip_header. create a new header with the param
8312882Svi117747 * and mark the old header as deleted.
8322882Svi117747 */
8332882Svi117747 sip_header_t
sip_add_param(sip_header_t sip_header,char * param,int * error)8342882Svi117747 sip_add_param(sip_header_t sip_header, char *param, int *error)
8352882Svi117747 {
8362882Svi117747 _sip_header_t *_sip_header;
8372882Svi117747 _sip_header_t *new_header;
8382882Svi117747 int hdrlen;
8392882Svi117747 _sip_msg_t *_sip_msg;
8402882Svi117747 int param_len;
8412882Svi117747 char *tmp_ptr;
8422882Svi117747
8432882Svi117747 if (error != NULL)
8442882Svi117747 *error = 0;
8452882Svi117747
8462882Svi117747 if (param == NULL || sip_header == NULL) {
8472882Svi117747 if (error != NULL)
8482882Svi117747 *error = EINVAL;
8492882Svi117747 return (NULL);
8502882Svi117747 }
8512882Svi117747
8522882Svi117747 _sip_header = (_sip_header_t *)sip_header;
8532882Svi117747
8542882Svi117747 (void) pthread_mutex_lock(&_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
8552882Svi117747 if (_sip_header->sip_hdr_sipmsg->sip_msg_cannot_be_modified) {
8562882Svi117747 if (error != NULL)
8572882Svi117747 *error = EPERM;
8582882Svi117747 (void) pthread_mutex_unlock(
8592882Svi117747 &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
8602882Svi117747 return (NULL);
8612882Svi117747 }
8622882Svi117747 if (_sip_header->sip_header_state == SIP_HEADER_DELETED) {
8632882Svi117747 if (error != NULL)
8642882Svi117747 *error = EINVAL;
8652882Svi117747 (void) pthread_mutex_unlock(
8662882Svi117747 &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
8672882Svi117747 return (NULL);
8682882Svi117747 }
8692882Svi117747
8702882Svi117747 param_len = SIP_SPACE_LEN + sizeof (char) + SIP_SPACE_LEN +
8712882Svi117747 strlen(param);
8722882Svi117747 hdrlen = _sip_header->sip_hdr_end - _sip_header->sip_hdr_start;
8732882Svi117747 new_header = sip_new_header(hdrlen + param_len);
8742882Svi117747 if (new_header == NULL) {
8752882Svi117747 if (error != NULL)
8762882Svi117747 *error = ENOMEM;
8772882Svi117747 (void) pthread_mutex_unlock(
8782882Svi117747 &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
8792882Svi117747 return (NULL);
8802882Svi117747 }
8812882Svi117747 (void) memcpy(new_header->sip_hdr_start, _sip_header->sip_hdr_start,
8822882Svi117747 hdrlen);
8832882Svi117747 new_header->sip_hdr_end = new_header->sip_hdr_start + hdrlen;
8842882Svi117747 hdrlen = param_len + 1;
8852882Svi117747 /*
8862882Svi117747 * Find CRLF
8872882Svi117747 */
8882882Svi117747 tmp_ptr = new_header->sip_hdr_end;
8892882Svi117747 while (*tmp_ptr-- != '\n') {
8902882Svi117747 hdrlen++;
8912882Svi117747 if (tmp_ptr == new_header->sip_hdr_start) {
8922882Svi117747 sip_free_header(new_header);
8932882Svi117747 if (error != NULL)
8942882Svi117747 *error = EINVAL;
8952882Svi117747 (void) pthread_mutex_unlock(
8962882Svi117747 &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
8972882Svi117747 return (NULL);
8982882Svi117747 }
8992882Svi117747 }
9002882Svi117747 (void) snprintf(tmp_ptr, hdrlen + 1,
9012882Svi117747 " %c %s%s", SIP_SEMI, param, SIP_CRLF);
9022882Svi117747 new_header->sip_hdr_end += param_len;
9032882Svi117747 new_header->sip_header_functions = _sip_header->sip_header_functions;
9042882Svi117747 _sip_msg = _sip_header->sip_hdr_sipmsg;
9052882Svi117747 _sip_add_header(_sip_msg, new_header, B_TRUE, B_FALSE, NULL);
9062882Svi117747 if (_sip_header->sip_hdr_sipmsg->sip_msg_buf != NULL)
9072882Svi117747 _sip_header->sip_hdr_sipmsg->sip_msg_modified = B_TRUE;
9082882Svi117747 (void) pthread_mutex_unlock(&new_header->sip_hdr_sipmsg->sip_msg_mutex);
9092882Svi117747 (void) sip_delete_header(sip_header);
9102882Svi117747 return ((sip_header_t)new_header);
9112882Svi117747 }
9122882Svi117747
9132882Svi117747 /*
9142882Svi117747 * Get Request URI
9152882Svi117747 */
9162882Svi117747 const struct sip_uri *
sip_get_request_uri(sip_msg_t sip_msg,int * error)9172882Svi117747 sip_get_request_uri(sip_msg_t sip_msg, int *error)
9182882Svi117747 {
9192882Svi117747 _sip_msg_t *_sip_msg;
9202882Svi117747 sip_message_type_t *sip_msg_info;
9212882Svi117747 const struct sip_uri *ret = NULL;
9222882Svi117747
9232882Svi117747 if (error != NULL)
9242882Svi117747 *error = 0;
9252882Svi117747
9262882Svi117747 if (sip_msg == NULL) {
9272882Svi117747 if (error != NULL)
9282882Svi117747 *error = EINVAL;
9292882Svi117747 return (NULL);
9302882Svi117747 }
9312882Svi117747 _sip_msg = (_sip_msg_t *)sip_msg;
9322882Svi117747 (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
9332882Svi117747 sip_msg_info = _sip_msg->sip_msg_req_res;
9342882Svi117747 if (sip_msg_info != NULL && sip_msg_info->is_request) {
9352882Svi117747 ret = sip_msg_info->sip_req_parse_uri;
9362882Svi117747 } else {
9372882Svi117747 if (error != NULL)
9382882Svi117747 *error = EINVAL;
9392882Svi117747 }
9402882Svi117747 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
9412882Svi117747
9422882Svi117747 if (ret != NULL) {
9432882Svi117747 if (ret->sip_uri_scheme.sip_str_len == 0 ||
9442882Svi117747 ret->sip_uri_scheme.sip_str_ptr == NULL) {
9452882Svi117747 ret = NULL;
9462882Svi117747 if (error != NULL)
9472882Svi117747 *error = EINVAL;
9482882Svi117747 } else if (ret->sip_uri_errflags != 0 && error != NULL) {
9492882Svi117747 *error = EINVAL;
9502882Svi117747 }
9512882Svi117747 }
9522882Svi117747 return ((sip_uri_t)ret);
9532882Svi117747 }
9542882Svi117747
9552882Svi117747 /*
9562882Svi117747 * returns a comma separated string of all the sent-by values registered by
9572882Svi117747 * the UA.
9582882Svi117747 */
9592882Svi117747 char *
sip_sent_by_to_str(int * error)9602882Svi117747 sip_sent_by_to_str(int *error)
9612882Svi117747 {
9622882Svi117747 sent_by_list_t *sb;
9632882Svi117747 int sb_len = 0;
9642882Svi117747 int slen;
9652882Svi117747 char *sb_str;
9662882Svi117747 char *p;
9672882Svi117747 int count = 0;
9682882Svi117747 int cnt = 0;
9692882Svi117747
9702882Svi117747 if (error != NULL)
9712882Svi117747 *error = 0;
9722882Svi117747
9732882Svi117747 (void) pthread_mutex_lock(&sip_sent_by_lock);
9742882Svi117747 if (sip_sent_by == NULL) {
9752882Svi117747 (void) pthread_mutex_unlock(&sip_sent_by_lock);
9762882Svi117747 return (NULL);
9772882Svi117747 }
9782882Svi117747 sb = sip_sent_by;
9792882Svi117747 for (cnt = 0; cnt < sip_sent_by_count; cnt++) {
9802882Svi117747 sb_len += strlen(sb->sb_val);
9812882Svi117747 sb = sb->sb_next;
9822882Svi117747 }
9832882Svi117747 /*
9842882Svi117747 * for the commas
9852882Svi117747 */
9862882Svi117747 sb_len += sip_sent_by_count - 1;
9872882Svi117747 sb_str = malloc(sb_len + 1);
9882882Svi117747 if (sb_str == NULL) {
9892882Svi117747 if (error != NULL)
9902882Svi117747 *error = ENOMEM;
9912882Svi117747 (void) pthread_mutex_unlock(&sip_sent_by_lock);
9922882Svi117747 return (NULL);
9932882Svi117747 }
9942882Svi117747 sb = sip_sent_by;
9952882Svi117747 p = sb_str;
9962882Svi117747 slen = sb_len + 1;
9972882Svi117747 for (cnt = 0; cnt < sip_sent_by_count; cnt++) {
9982882Svi117747 if (cnt == 0) {
9992882Svi117747 count = snprintf(p, slen, "%s", sb->sb_val);
10002882Svi117747 } else {
10012882Svi117747 count = snprintf(p, slen, "%c%s", SIP_COMMA,
10022882Svi117747 sb->sb_val);
10032882Svi117747 }
10042882Svi117747 p += count;
10052882Svi117747 slen -= count;
10062882Svi117747 sb = sb->sb_next;
10072882Svi117747 }
10082882Svi117747 sb_str[sb_len] = '\0';
10092882Svi117747 (void) pthread_mutex_unlock(&sip_sent_by_lock);
10102882Svi117747 return (sb_str);
10112882Svi117747 }
10122882Svi117747
10132882Svi117747 /*
10142882Svi117747 * A comma separated list of sent-by values.
10152882Svi117747 */
10162882Svi117747 int
sip_register_sent_by(char * val)10172882Svi117747 sip_register_sent_by(char *val)
10182882Svi117747 {
10192882Svi117747 sent_by_list_t *sb = NULL;
10202882Svi117747 sent_by_list_t *sb_tail = NULL;
10212882Svi117747 char *str;
10222882Svi117747 int count = 0;
10232882Svi117747
10242882Svi117747 if (val == NULL)
10252882Svi117747 return (EINVAL);
10262882Svi117747 str = strtok(val, ",");
10272882Svi117747 while (str != NULL) {
10282882Svi117747 int slen;
10292882Svi117747 char *start = str;
10302882Svi117747 char *end = str + strlen(str) - 1;
10312882Svi117747
10322882Svi117747 while (isspace(*start))
10332882Svi117747 start++;
10342882Svi117747 while (isspace(*end))
10352882Svi117747 end--;
10362882Svi117747 if (end <= start)
10372882Svi117747 goto err_ret;
10382882Svi117747 slen = end - start + 1;
10392882Svi117747 sb_tail = (sent_by_list_t *)malloc(sizeof (*sb_tail));
10402882Svi117747 if (sb_tail == NULL)
10412882Svi117747 goto err_ret;
10422882Svi117747 sb_tail->sb_next = sb_tail->sb_prev = NULL;
10432882Svi117747 if ((sb_tail->sb_val = (char *)malloc(slen + 1)) == NULL) {
10442882Svi117747 free(sb_tail);
10452882Svi117747 goto err_ret;
10462882Svi117747 }
10472882Svi117747 (void) strncpy(sb_tail->sb_val, start, slen);
10482882Svi117747 sb_tail->sb_val[slen] = '\0';
10492882Svi117747 if (sb == NULL) {
10502882Svi117747 sb = sb_tail;
10512882Svi117747 } else {
10522882Svi117747 sb_tail->sb_next = sb;
10532882Svi117747 sb->sb_prev = sb_tail;
10542882Svi117747 sb = sb_tail;
10552882Svi117747 }
10562882Svi117747 count++;
10572882Svi117747 str = strtok(NULL, ",");
10582882Svi117747 }
10592882Svi117747 sb_tail = sb;
10602882Svi117747 while (sb_tail->sb_next != NULL)
10612882Svi117747 sb_tail = sb_tail->sb_next;
10622882Svi117747 (void) pthread_mutex_lock(&sip_sent_by_lock);
10632882Svi117747 if (sip_sent_by != NULL) {
10642882Svi117747 sb_tail->sb_next = sip_sent_by;
10652882Svi117747 sip_sent_by->sb_prev = sb_tail;
10662882Svi117747 }
10672882Svi117747 sip_sent_by = sb;
10682882Svi117747 sip_sent_by_count += count;
10692882Svi117747 (void) pthread_mutex_unlock(&sip_sent_by_lock);
10702882Svi117747 return (0);
10712882Svi117747 err_ret:
10722882Svi117747 sb_tail = sb;
10732882Svi117747 for (; count > 0; count--) {
10742882Svi117747 sb = sb_tail->sb_next;
10752882Svi117747 free(sb_tail->sb_val);
10762882Svi117747 sb_tail->sb_next = NULL;
10772882Svi117747 sb_tail->sb_prev = NULL;
10782882Svi117747 free(sb_tail);
10792882Svi117747 sb_tail = sb;
10802882Svi117747 }
10812882Svi117747 return (EINVAL);
10822882Svi117747 }
10832882Svi117747
10842882Svi117747 /*
10852882Svi117747 * Un-register sent-by values; 'val' contains a comma separated list
10862882Svi117747 */
10872882Svi117747 void
sip_unregister_sent_by(char * val)10882882Svi117747 sip_unregister_sent_by(char *val)
10892882Svi117747 {
10902882Svi117747 sent_by_list_t *sb;
10912882Svi117747 char *str;
10922882Svi117747 int count = 0;
10932882Svi117747
10942882Svi117747 (void) pthread_mutex_lock(&sip_sent_by_lock);
10952882Svi117747 str = strtok(val, ",");
10962882Svi117747 while (str != NULL) {
10972882Svi117747 sb = sip_sent_by;
10982882Svi117747 for (count = 0; count < sip_sent_by_count; count++) {
10992882Svi117747 if (strncmp(sb->sb_val, str, strlen(str)) == 0) {
11002882Svi117747 if (sb == sip_sent_by) {
11012882Svi117747 if (sb->sb_next != NULL)
11022882Svi117747 sip_sent_by = sb->sb_next;
11032882Svi117747 else
11042882Svi117747 sip_sent_by = NULL;
11052882Svi117747 } else if (sb->sb_next == NULL) {
11062882Svi117747 sb->sb_prev->sb_next = NULL;
11072882Svi117747 } else {
11082882Svi117747 sb->sb_prev->sb_next = sb->sb_next;
11092882Svi117747 sb->sb_next->sb_prev = sb->sb_prev;
11102882Svi117747 }
11112882Svi117747 sip_sent_by_count--;
11122882Svi117747 sb->sb_next = NULL;
11132882Svi117747 sb->sb_prev = NULL;
11142882Svi117747 free(sb->sb_val);
11152882Svi117747 free(sb);
11162882Svi117747 break;
11172882Svi117747 }
11182882Svi117747 sb = sb->sb_next;
11192882Svi117747 }
11202882Svi117747 str = strtok(NULL, ",");
11212882Svi117747 }
11222882Svi117747 (void) pthread_mutex_unlock(&sip_sent_by_lock);
11232882Svi117747 }
11242882Svi117747
11252882Svi117747 /*
11262882Svi117747 * Un-register all the sent-by values
11272882Svi117747 */
11282882Svi117747 void
sip_unregister_all_sent_by()11292882Svi117747 sip_unregister_all_sent_by()
11302882Svi117747 {
11312882Svi117747 sent_by_list_t *sb;
11322882Svi117747 int count;
11332882Svi117747
11342882Svi117747 (void) pthread_mutex_lock(&sip_sent_by_lock);
11352882Svi117747 sb = sip_sent_by;
11362882Svi117747 for (count = 0; count < sip_sent_by_count; count++) {
11372882Svi117747 sip_sent_by = sb->sb_next;
11382882Svi117747 free(sb->sb_val);
11392882Svi117747 sb->sb_next = NULL;
11402882Svi117747 sb->sb_prev = NULL;
11412882Svi117747 free(sb);
11422882Svi117747 sb = sip_sent_by;
11432882Svi117747 }
11442882Svi117747 sip_sent_by = NULL;
11452882Svi117747 sip_sent_by_count = 0;
11462882Svi117747 (void) pthread_mutex_unlock(&sip_sent_by_lock);
11472882Svi117747 }
11482882Svi117747
11492882Svi117747 /*
11502882Svi117747 * Given a response code, return the corresponding phrase
11512882Svi117747 */
11522882Svi117747 char *
sip_get_resp_desc(int resp_code)11532882Svi117747 sip_get_resp_desc(int resp_code)
11542882Svi117747 {
11552882Svi117747 switch (resp_code) {
11562882Svi117747 case SIP_TRYING:
11572882Svi117747 return ("TRYING");
11582882Svi117747 case SIP_RINGING:
11592882Svi117747 return ("RINGING");
11602882Svi117747 case SIP_CALL_IS_BEING_FORWARDED:
11612882Svi117747 return ("CALL_IS_BEING_FORWARDED");
11622882Svi117747 case SIP_QUEUED:
11632882Svi117747 return ("QUEUED");
11642882Svi117747 case SIP_SESSION_PROGRESS:
11652882Svi117747 return ("SESSION_PROGRESS");
11662882Svi117747 case SIP_OK:
11672882Svi117747 return ("OK");
11682882Svi117747 case SIP_ACCEPTED:
11692882Svi117747 return ("ACCEPTED");
11702882Svi117747 case SIP_MULTIPLE_CHOICES:
11712882Svi117747 return ("MULTIPLE_CHOICES");
11722882Svi117747 case SIP_MOVED_PERMANENTLY:
11732882Svi117747 return ("MOVED_PERMANENTLY");
11742882Svi117747 case SIP_MOVED_TEMPORARILY:
11752882Svi117747 return ("MOVED_TEMPORARILY");
11762882Svi117747 case SIP_USE_PROXY:
11772882Svi117747 return ("USE_PROXY");
11782882Svi117747 case SIP_ALTERNATIVE_SERVICE:
11792882Svi117747 return ("ALTERNATIVE_SERVICE");
11802882Svi117747 case SIP_BAD_REQUEST:
11812882Svi117747 return ("BAD_REQUEST");
11822882Svi117747 case SIP_UNAUTHORIZED:
11832882Svi117747 return ("UNAUTHORIZED");
11842882Svi117747 case SIP_PAYMENT_REQUIRED:
11852882Svi117747 return ("PAYMENT_REQUIRED");
11862882Svi117747 case SIP_FORBIDDEN:
11872882Svi117747 return ("FORBIDDEN");
11882882Svi117747 case SIP_NOT_FOUND:
11892882Svi117747 return ("NOT_FOUND");
11902882Svi117747 case SIP_METHOD_NOT_ALLOWED:
11912882Svi117747 return ("METHOD_NOT_ALLOWED");
11922882Svi117747 case SIP_NOT_ACCEPTABLE:
11932882Svi117747 return ("NOT_ACCEPTABLE");
11942882Svi117747 case SIP_PROXY_AUTH_REQUIRED:
11952882Svi117747 return ("PROXY_AUTH_REQUIRED");
11962882Svi117747 case SIP_REQUEST_TIMEOUT:
11972882Svi117747 return ("REQUEST_TIMEOUT");
11982882Svi117747 case SIP_GONE:
11992882Svi117747 return ("GONE");
12002882Svi117747 case SIP_REQUEST_ENTITY_2_LARGE:
12012882Svi117747 return ("REQUEST_ENTITY_2_LARGE");
12022882Svi117747 case SIP_REQUEST_URI_2_LONG:
12032882Svi117747 return ("REQUEST_URI_2_LONG");
12042882Svi117747 case SIP_UNSUPPORTED_MEDIA_TYPE:
12052882Svi117747 return ("UNSUPPORTED_MEDIA_TYPE");
12062882Svi117747 case SIP_UNSUPPORTED_URI_SCHEME:
12072882Svi117747 return ("UNSUPPORTED_URI_SCHEME");
12082882Svi117747 case SIP_BAD_EXTENSION:
12092882Svi117747 return ("BAD_EXTENSION");
12102882Svi117747 case SIP_EXTENSION_REQUIRED:
12112882Svi117747 return ("EXTENSION_REQUIRED");
12122882Svi117747 case SIP_INTERVAL_2_BRIEF:
12132882Svi117747 return ("INTERVAL_2_BRIEF");
12142882Svi117747 case SIP_TEMPORARILY_UNAVAIL:
12152882Svi117747 return ("TEMPORARILY_UNAVAIL");
12162882Svi117747 case SIP_CALL_NON_EXISTANT:
12172882Svi117747 return ("CALL_NON_EXISTANT");
12182882Svi117747 case SIP_LOOP_DETECTED:
12192882Svi117747 return ("LOOP_DETECTED");
12202882Svi117747 case SIP_TOO_MANY_HOOPS:
12212882Svi117747 return ("TOO_MANY_HOOPS");
12222882Svi117747 case SIP_ADDRESS_INCOMPLETE:
12232882Svi117747 return ("ADDRESS_INCOMPLETE");
12242882Svi117747 case SIP_AMBIGUOUS:
12252882Svi117747 return ("AMBIGUOUS");
12262882Svi117747 case SIP_BUSY_HERE:
12272882Svi117747 return ("BUSY_HERE");
12282882Svi117747 case SIP_REQUEST_TERMINATED:
12292882Svi117747 return ("REQUEST_TERMINATED");
12302882Svi117747 case SIP_NOT_ACCEPTABLE_HERE:
12312882Svi117747 return ("NOT_ACCEPTABLE_HERE");
12322882Svi117747 case SIP_BAD_EVENT:
12332882Svi117747 return ("BAD_EVENT");
12342882Svi117747 case SIP_REQUEST_PENDING:
12352882Svi117747 return ("REQUEST_PENDING");
12362882Svi117747 case SIP_UNDECIPHERABLE:
12372882Svi117747 return ("UNDECIPHERABLE");
12382882Svi117747 case SIP_SERVER_INTERNAL_ERROR:
12392882Svi117747 return ("SERVER_INTERNAL_ERROR");
12402882Svi117747 case SIP_NOT_IMPLEMENTED:
12412882Svi117747 return ("NOT_IMPLEMENTED");
12422882Svi117747 case SIP_BAD_GATEWAY:
12432882Svi117747 return ("BAD_GATEWAY");
12442882Svi117747 case SIP_SERVICE_UNAVAILABLE:
12452882Svi117747 return ("SERVICE_UNAVAILABLE");
12462882Svi117747 case SIP_SERVER_TIMEOUT:
12472882Svi117747 return ("SERVER_TIMEOUT");
12482882Svi117747 case SIP_VERSION_NOT_SUPPORTED:
12492882Svi117747 return ("VERSION_NOT_SUPPORTED");
12502882Svi117747 case SIP_MESSAGE_2_LARGE:
12512882Svi117747 return ("MESSAGE_2_LARGE");
12522882Svi117747 case SIP_BUSY_EVERYWHERE:
12532882Svi117747 return ("BUSY_EVERYWHERE");
12542882Svi117747 case SIP_DECLINE:
12552882Svi117747 return ("DECLINE");
12562882Svi117747 case SIP_DOES_NOT_EXIST_ANYWHERE:
12572882Svi117747 return ("DOES_NOT_EXIST_ANYWHERE");
12582882Svi117747 case SIP_NOT_ACCEPTABLE_ANYWHERE:
12592882Svi117747 return ("NOT_ACCEPTABLE_ANYWHERE");
12602882Svi117747 default:
12612882Svi117747 return ("UNKNOWN");
12622882Svi117747 }
12632882Svi117747 }
12642882Svi117747
12652882Svi117747 /*
12662882Svi117747 * The following three fns initialize and destroy the private library
12672882Svi117747 * data in sip_conn_object_t. The assumption is that the 1st member
12682882Svi117747 * of sip_conn_object_t is reserved for library use. The private data
12692882Svi117747 * is used only for byte-stream protocols such as TCP to accumulate
12702882Svi117747 * a complete SIP message, based on the CONTENT-LENGTH value, before
12712882Svi117747 * processing it.
12722882Svi117747 */
12732882Svi117747 int
sip_init_conn_object(sip_conn_object_t obj)12742882Svi117747 sip_init_conn_object(sip_conn_object_t obj)
12752882Svi117747 {
12762882Svi117747 void **obj_val;
12772882Svi117747 sip_conn_obj_pvt_t *pvt_data;
12782882Svi117747
12792882Svi117747 if (obj == NULL)
12802882Svi117747 return (EINVAL);
12812882Svi117747 pvt_data = malloc(sizeof (sip_conn_obj_pvt_t));
12822882Svi117747 if (pvt_data == NULL)
12832882Svi117747 return (ENOMEM);
12842882Svi117747 pvt_data->sip_conn_obj_cache = NULL;
12852882Svi117747 pvt_data->sip_conn_obj_reass = malloc(sizeof (sip_reass_entry_t));
12862882Svi117747 if (pvt_data->sip_conn_obj_reass == NULL) {
12872882Svi117747 free(pvt_data);
12882882Svi117747 return (ENOMEM);
12892882Svi117747 }
12902882Svi117747 bzero(pvt_data->sip_conn_obj_reass, sizeof (sip_reass_entry_t));
12912882Svi117747 (void) pthread_mutex_init(&pvt_data->sip_conn_obj_reass_lock, NULL);
12922882Svi117747 (void) pthread_mutex_init(&pvt_data->sip_conn_obj_cache_lock, NULL);
12932882Svi117747 sip_refhold_conn(obj);
12942882Svi117747 obj_val = (void *)obj;
12952882Svi117747 *obj_val = (void *)pvt_data;
12962882Svi117747
12972882Svi117747 return (0);
12982882Svi117747 }
12992882Svi117747
13002882Svi117747 /*
13012882Svi117747 * Clear private date, if any
13022882Svi117747 */
13032882Svi117747 void
sip_clear_stale_data(sip_conn_object_t obj)13042882Svi117747 sip_clear_stale_data(sip_conn_object_t obj)
13052882Svi117747 {
13062882Svi117747 void **obj_val;
13072882Svi117747 sip_conn_obj_pvt_t *pvt_data;
13082882Svi117747 sip_reass_entry_t *reass;
13092882Svi117747
13102882Svi117747 if (obj == NULL)
13112882Svi117747 return;
13122882Svi117747 obj_val = (void *)obj;
13132882Svi117747 pvt_data = (sip_conn_obj_pvt_t *)*obj_val;
13142882Svi117747 (void) pthread_mutex_lock(&pvt_data->sip_conn_obj_reass_lock);
13152882Svi117747 reass = pvt_data->sip_conn_obj_reass;
13162882Svi117747 if (reass->sip_reass_msg != NULL) {
13172882Svi117747 assert(reass->sip_reass_msglen > 0);
13182882Svi117747 free(reass->sip_reass_msg);
13192882Svi117747 reass->sip_reass_msglen = 0;
13202882Svi117747 }
13212882Svi117747 assert(reass->sip_reass_msglen == 0);
13222882Svi117747 (void) pthread_mutex_unlock(&pvt_data->sip_conn_obj_reass_lock);
13232882Svi117747 }
13242882Svi117747
13252882Svi117747 /*
13262882Svi117747 * Walk through all the transactions, remove if this obj has been cached
13272882Svi117747 * by any.
13282882Svi117747 */
13292882Svi117747 void
sip_conn_destroyed(sip_conn_object_t obj)13302882Svi117747 sip_conn_destroyed(sip_conn_object_t obj)
13312882Svi117747 {
13322882Svi117747 void **obj_val;
13332882Svi117747 sip_conn_obj_pvt_t *pvt_data;
13342882Svi117747
13352882Svi117747 if (obj == NULL)
13362882Svi117747 return;
13372882Svi117747 obj_val = (void *)obj;
13382882Svi117747 pvt_data = (sip_conn_obj_pvt_t *)*obj_val;
13392882Svi117747
13402882Svi117747 sip_clear_stale_data(obj);
13412882Svi117747 free(pvt_data->sip_conn_obj_reass);
13422882Svi117747 pvt_data->sip_conn_obj_reass = NULL;
13432882Svi117747 (void) pthread_mutex_destroy(&pvt_data->sip_conn_obj_reass_lock);
13442882Svi117747
13452882Svi117747 sip_del_conn_obj_cache(obj, NULL);
13462882Svi117747 (void) pthread_mutex_destroy(&pvt_data->sip_conn_obj_cache_lock);
13472882Svi117747
13482882Svi117747 free(pvt_data);
13492882Svi117747 *obj_val = NULL;
13502882Svi117747 sip_refrele_conn(obj);
13512882Svi117747 }
1352