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