xref: /onnv-gate/usr/src/lib/libsip/common/sip_msg.c (revision 3439:0302bfe973fe)
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 <assert.h>
31*3439Svi117747 #include <errno.h>
32*3439Svi117747 #include <pthread.h>
33*3439Svi117747 #include <stdlib.h>
34*3439Svi117747 #include <string.h>
35*3439Svi117747 #include <sip.h>
36*3439Svi117747 
372882Svi117747 #include "sip_msg.h"
382882Svi117747 #include "sip_miscdefs.h"
392882Svi117747 #include "sip_parse_generic.h"
402882Svi117747 
412882Svi117747 /*
422882Svi117747  * Response consists of SIP version, response code, response phrase and CRLF.
432882Svi117747  */
442882Svi117747 #define	SIP_RESPONSE	"%s %d %s%s"
452882Svi117747 
462882Svi117747 void sip_free_content(_sip_msg_t *);
472882Svi117747 
482882Svi117747 /*
492882Svi117747  * Allocate a new sip msg struct.
502882Svi117747  */
512882Svi117747 sip_msg_t
sip_new_msg()522882Svi117747 sip_new_msg()
532882Svi117747 {
542882Svi117747 	_sip_msg_t *sip_msg;
552882Svi117747 
562882Svi117747 	sip_msg = calloc(1, sizeof (_sip_msg_t));
572882Svi117747 	if (sip_msg != NULL) {
582882Svi117747 		sip_msg->sip_msg_ref_cnt = 1;
592882Svi117747 		(void) pthread_mutex_init(&sip_msg->sip_msg_mutex, NULL);
602882Svi117747 	}
612882Svi117747 	return ((sip_msg_t)sip_msg);
622882Svi117747 }
632882Svi117747 
642882Svi117747 /*
652882Svi117747  * Free all resources. The lock is taken by SIP_MSG_REFCNT_DECR. The
662882Svi117747  * thread that decrements the last refcount should take care that
672882Svi117747  * the message is not accessible to other threads before doing so.
682882Svi117747  * Else, if the message is still accessible to others, it is
692882Svi117747  * possible that the other thread could be waiting to take the
702882Svi117747  * lock when we proceed to destroy it.
712882Svi117747  */
722882Svi117747 void
sip_destroy_msg(_sip_msg_t * _sip_msg)732882Svi117747 sip_destroy_msg(_sip_msg_t *_sip_msg)
742882Svi117747 {
752882Svi117747 #ifdef	__solaris__
762882Svi117747 	assert(mutex_held(&_sip_msg->sip_msg_mutex));
772882Svi117747 #endif
782882Svi117747 	(void) sip_delete_start_line_locked(_sip_msg);
792882Svi117747 	assert(_sip_msg->sip_msg_ref_cnt == 0);
802882Svi117747 	sip_delete_all_headers((sip_msg_t)_sip_msg);
812882Svi117747 	sip_free_content(_sip_msg);
822882Svi117747 	if (_sip_msg->sip_msg_buf != NULL)
832882Svi117747 		free(_sip_msg->sip_msg_buf);
842882Svi117747 
852882Svi117747 	if (_sip_msg->sip_msg_old_buf != NULL)
862882Svi117747 		free(_sip_msg->sip_msg_old_buf);
872882Svi117747 
882882Svi117747 	while (_sip_msg->sip_msg_req_res != NULL) {
892882Svi117747 		sip_message_type_t	*sip_msg_type_ptr;
902882Svi117747 
912882Svi117747 		sip_msg_type_ptr = _sip_msg->sip_msg_req_res->sip_next;
922882Svi117747 		if (_sip_msg->sip_msg_req_res->is_request) {
932882Svi117747 			sip_request_t	*reqline;
942882Svi117747 
952882Svi117747 			reqline = &_sip_msg->sip_msg_req_res->U.sip_request;
962882Svi117747 			if (reqline->sip_parse_uri != NULL) {
972882Svi117747 				sip_free_parsed_uri(reqline->sip_parse_uri);
982882Svi117747 				reqline->sip_parse_uri = NULL;
992882Svi117747 			}
1002882Svi117747 		}
1012882Svi117747 		free(_sip_msg->sip_msg_req_res);
1022882Svi117747 		_sip_msg->sip_msg_req_res = sip_msg_type_ptr;
1032882Svi117747 	}
1042882Svi117747 	(void) pthread_mutex_destroy(&_sip_msg->sip_msg_mutex);
1052882Svi117747 	free(_sip_msg);
1062882Svi117747 }
1072882Svi117747 
1082882Svi117747 /*
1092882Svi117747  * Free a sip msg struct.
1102882Svi117747  */
1112882Svi117747 void
sip_free_msg(sip_msg_t sip_msg)1122882Svi117747 sip_free_msg(sip_msg_t sip_msg)
1132882Svi117747 {
1142882Svi117747 	if (sip_msg == NULL)
1152882Svi117747 		return;
1162882Svi117747 
1172882Svi117747 	SIP_MSG_REFCNT_DECR((_sip_msg_t *)sip_msg);
1182882Svi117747 }
1192882Svi117747 
1202882Svi117747 /*
1212882Svi117747  * Hold a sip msg struct.
1222882Svi117747  */
1232882Svi117747 void
sip_hold_msg(sip_msg_t sip_msg)1242882Svi117747 sip_hold_msg(sip_msg_t sip_msg)
1252882Svi117747 {
1262882Svi117747 
1272882Svi117747 	if (sip_msg == NULL)
1282882Svi117747 		return;
1292882Svi117747 
1302882Svi117747 	SIP_MSG_REFCNT_INCR((_sip_msg_t *)sip_msg);
1312882Svi117747 }
1322882Svi117747 
1332882Svi117747 /*
1342882Svi117747  * Clone a message
1352882Svi117747  */
1362882Svi117747 sip_msg_t
sip_clone_msg(sip_msg_t sip_msg)1372882Svi117747 sip_clone_msg(sip_msg_t sip_msg)
1382882Svi117747 {
1392882Svi117747 	_sip_msg_t	*new_msg;
1402882Svi117747 	_sip_msg_t	*_sip_msg;
1412882Svi117747 	sip_content_t	*sip_content;
1422882Svi117747 	sip_content_t	*msg_content;
1432882Svi117747 	sip_content_t	*new_content = NULL;
1442882Svi117747 	int		len;
1452882Svi117747 
1462882Svi117747 	if (sip_msg == NULL)
1472882Svi117747 		return (NULL);
1482882Svi117747 	new_msg = (_sip_msg_t *)sip_new_msg();
1492882Svi117747 	if (new_msg == NULL)
1502882Svi117747 		return (NULL);
1512882Svi117747 	_sip_msg = (_sip_msg_t *)sip_msg;
1522882Svi117747 	/*
1532882Svi117747 	 * Get start line
1542882Svi117747 	 */
1552882Svi117747 	if (sip_copy_start_line(_sip_msg, new_msg) != 0) {
1562882Svi117747 		sip_free_msg((sip_msg_t)new_msg);
1572882Svi117747 		return (NULL);
1582882Svi117747 	}
1592882Svi117747 	if (sip_copy_all_headers(_sip_msg, new_msg) != 0) {
1602882Svi117747 		sip_free_msg((sip_msg_t)new_msg);
1612882Svi117747 		return (NULL);
1622882Svi117747 	}
1632882Svi117747 	(void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
1642882Svi117747 	sip_content = _sip_msg->sip_msg_content;
1652882Svi117747 	while (sip_content != NULL) {
1662882Svi117747 		msg_content = calloc(1, sizeof (sip_content_t));
1672882Svi117747 		if (msg_content == NULL) {
1682882Svi117747 			sip_free_msg((sip_msg_t)new_msg);
1692882Svi117747 			(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
1702882Svi117747 			return (NULL);
1712882Svi117747 		}
1722882Svi117747 		len = sip_content->sip_content_end -
1732882Svi117747 		    sip_content->sip_content_start;
1742882Svi117747 		msg_content->sip_content_start = malloc(len + 1);
1752882Svi117747 		if (msg_content->sip_content_start == NULL) {
1762882Svi117747 			sip_free_msg((sip_msg_t)new_msg);
1772882Svi117747 			(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
1782882Svi117747 			return (NULL);
1792882Svi117747 		}
1802882Svi117747 		(void) strncpy(msg_content->sip_content_start,
1812882Svi117747 		    sip_content->sip_content_start, len);
1822882Svi117747 		msg_content->sip_content_start[len] = '\0';
1832882Svi117747 		msg_content->sip_content_current =
1842882Svi117747 		    msg_content->sip_content_start;
1852882Svi117747 		msg_content->sip_content_end =  msg_content->sip_content_start +
1862882Svi117747 		    len;
1872882Svi117747 		msg_content->sip_content_allocated = B_TRUE;
1882882Svi117747 		new_msg->sip_msg_content_len += len;
1892882Svi117747 		new_msg->sip_msg_len += len;
1902882Svi117747 		if (new_msg->sip_msg_content == NULL)
1912882Svi117747 			new_msg->sip_msg_content = msg_content;
1922882Svi117747 		else
1932882Svi117747 			new_content->sip_content_next = msg_content;
1942882Svi117747 		new_content = msg_content;
1952882Svi117747 		sip_content = sip_content->sip_content_next;
1962882Svi117747 	}
1972882Svi117747 	(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
1982882Svi117747 	/*
1992882Svi117747 	 * Since this is a new message, no threads should be referring
2002882Svi117747 	 * to this, so it is not necessary to take the lock, however,
2012882Svi117747 	 * since sip_msg_to_msgbuf() expects the lock to be held, we'll
2022882Svi117747 	 * take it here.
2032882Svi117747 	 */
2042882Svi117747 	(void) pthread_mutex_lock(&new_msg->sip_msg_mutex);
2052882Svi117747 	new_msg->sip_msg_buf = sip_msg_to_msgbuf((sip_msg_t)new_msg, NULL);
2062882Svi117747 	if (new_msg->sip_msg_buf == NULL) {
2072882Svi117747 		(void) pthread_mutex_unlock(&new_msg->sip_msg_mutex);
2082882Svi117747 		sip_free_msg((sip_msg_t)new_msg);
2092882Svi117747 		return (NULL);
2102882Svi117747 	}
2112882Svi117747 	new_msg->sip_msg_cannot_be_modified = B_TRUE;
2122882Svi117747 	(void) pthread_mutex_unlock(&new_msg->sip_msg_mutex);
2132882Svi117747 
2142882Svi117747 	return ((sip_msg_t)new_msg);
2152882Svi117747 }
2162882Svi117747 
2172882Svi117747 /*
2182882Svi117747  * Return the SIP message as a string. Caller frees the string
2192882Svi117747  */
2202882Svi117747 char *
sip_msg_to_str(sip_msg_t sip_msg,int * error)2212882Svi117747 sip_msg_to_str(sip_msg_t sip_msg, int *error)
2222882Svi117747 {
2232882Svi117747 	_sip_msg_t	*msg;
2242882Svi117747 	char		*msgstr;
2252882Svi117747 
2262882Svi117747 	if (sip_msg == NULL) {
2272882Svi117747 		if (error != NULL)
2282882Svi117747 			*error = EINVAL;
2292882Svi117747 		return (NULL);
2302882Svi117747 	}
2312882Svi117747 	msg = (_sip_msg_t *)sip_msg;
2322882Svi117747 	(void) pthread_mutex_lock(&msg->sip_msg_mutex);
2332882Svi117747 	msgstr = sip_msg_to_msgbuf(msg, error);
2342882Svi117747 	(void) pthread_mutex_unlock(&msg->sip_msg_mutex);
2352882Svi117747 	return (msgstr);
2362882Svi117747 }
2372882Svi117747 
2382882Svi117747 /*
2392882Svi117747  * Given a message generate a string that includes all the headers and the
2402882Svi117747  * content.
2412882Svi117747  */
2422882Svi117747 char *
sip_msg_to_msgbuf(_sip_msg_t * msg,int * error)2432882Svi117747 sip_msg_to_msgbuf(_sip_msg_t *msg, int *error)
2442882Svi117747 {
2452882Svi117747 	_sip_header_t	*header;
2462882Svi117747 	int		len = 0;
2472882Svi117747 	char		*p;
2482882Svi117747 	char		*e;
2492882Svi117747 	sip_content_t	*sip_content;
2502882Svi117747 #ifdef	_DEBUG
2512882Svi117747 	int		tlen = 0;
2522882Svi117747 	int		clen = 0;
2532882Svi117747 #endif
2542882Svi117747 
2552882Svi117747 	if (error != NULL)
2562882Svi117747 		*error = 0;
2572882Svi117747 
2582882Svi117747 	if (msg == NULL) {
2592882Svi117747 		if (error != NULL)
2602882Svi117747 			*error = EINVAL;
2612882Svi117747 		return (NULL);
2622882Svi117747 	}
2632882Svi117747 #ifdef	__solaris__
2642882Svi117747 	assert(mutex_held(&msg->sip_msg_mutex));
2652882Svi117747 #endif
2662882Svi117747 
2672882Svi117747 	p = (char *)malloc(msg->sip_msg_len + 1);
2682882Svi117747 	if (p == NULL) {
2692882Svi117747 		if (error != 0)
2702882Svi117747 			*error = ENOMEM;
2712882Svi117747 		return (NULL);
2722882Svi117747 	}
2732882Svi117747 	e = p;
2742882Svi117747 
2752882Svi117747 	/*
2762882Svi117747 	 * Get the start line
2772882Svi117747 	 */
2782882Svi117747 	if (msg->sip_msg_start_line != NULL) {
2792882Svi117747 		len = msg->sip_msg_start_line->sip_hdr_end -
2802882Svi117747 		    msg->sip_msg_start_line->sip_hdr_start;
2812882Svi117747 		(void) strncpy(e, msg->sip_msg_start_line->sip_hdr_start, len);
2822882Svi117747 		e += len;
2832882Svi117747 #ifdef	_DEBUG
2842882Svi117747 		tlen += len;
2852882Svi117747 #endif
2862882Svi117747 	}
2872882Svi117747 	header = sip_search_for_header(msg, NULL, NULL);
2882882Svi117747 	while (header != NULL) {
2892882Svi117747 		if (header->sip_header_state != SIP_HEADER_DELETED) {
2902882Svi117747 			if (header->sip_header_state ==
2912882Svi117747 			    SIP_HEADER_DELETED_VAL) {
2922882Svi117747 				len = sip_copy_values(e, header);
2932882Svi117747 			} else {
2942882Svi117747 				len = header->sip_hdr_end -
2952882Svi117747 				    header->sip_hdr_start;
2962882Svi117747 				(void) strncpy(e, header->sip_hdr_start, len);
2972882Svi117747 			}
2982882Svi117747 #ifdef	_DEBUG
2992882Svi117747 			tlen += len;
3002882Svi117747 			assert(tlen <= msg->sip_msg_len);
3012882Svi117747 #endif
3022882Svi117747 		}
3032882Svi117747 		header = sip_search_for_header(msg, NULL, header);
3042882Svi117747 		e += len;
3052882Svi117747 	}
3062882Svi117747 	sip_content = msg->sip_msg_content;
3072882Svi117747 	while (sip_content != NULL) {
3082882Svi117747 		len = sip_content->sip_content_end -
3092882Svi117747 		    sip_content->sip_content_start;
3102882Svi117747 #ifdef	_DEBUG
3112882Svi117747 		clen += len;
3122882Svi117747 		assert(clen <= msg->sip_msg_content_len);
3132882Svi117747 		tlen += len;
3142882Svi117747 		assert(tlen <= msg->sip_msg_len);
3152882Svi117747 #endif
3162882Svi117747 		(void) strncpy(e, sip_content->sip_content_start, len);
3172882Svi117747 		e += len;
3182882Svi117747 		sip_content = sip_content->sip_content_next;
3192882Svi117747 	}
3202882Svi117747 	p[msg->sip_msg_len] = '\0';
3212882Svi117747 	return (p);
3222882Svi117747 }
3232882Svi117747 
3242882Svi117747 /*
3252882Svi117747  * This is called just before sending the message to the transport. It
3262882Svi117747  * creates the sip_msg_buf from the SIP headers.
3272882Svi117747  */
3282882Svi117747 int
sip_adjust_msgbuf(_sip_msg_t * msg)3292882Svi117747 sip_adjust_msgbuf(_sip_msg_t *msg)
3302882Svi117747 {
3312882Svi117747 	_sip_header_t	*header;
3322882Svi117747 	int		ret;
3332882Svi117747 #ifdef	_DEBUG
3342882Svi117747 	int		tlen = 0;
3352882Svi117747 	int		clen = 0;
3362882Svi117747 #endif
3372882Svi117747 
3382882Svi117747 	if (msg == NULL)
3392882Svi117747 		return (EINVAL);
3402882Svi117747 
3412882Svi117747 	(void) pthread_mutex_lock(&msg->sip_msg_mutex);
3422882Svi117747 	if ((msg->sip_msg_buf != NULL) && (!msg->sip_msg_modified)) {
3432882Svi117747 		/*
3442882Svi117747 		 * We could just be forwarding the message we
3452882Svi117747 		 * received.
3462882Svi117747 		 */
3472882Svi117747 		(void) pthread_mutex_unlock(&msg->sip_msg_mutex);
3482882Svi117747 		return (0);
3492882Svi117747 	}
3502882Svi117747 
3512882Svi117747 	/*
3522882Svi117747 	 * We are sending a new message or a message that we received
3532882Svi117747 	 * but have modified it. We keep the old
3542882Svi117747 	 * msgbuf till the message is freed as some
3552882Svi117747 	 * headers still point to it.
3562882Svi117747 	 */
3572882Svi117747 
3582882Svi117747 	assert(msg->sip_msg_old_buf == NULL);
3592882Svi117747 	msg->sip_msg_old_buf = msg->sip_msg_buf;
3602882Svi117747 	/*
3612882Svi117747 	 * We add the content-length header here, if it has not
3622882Svi117747 	 * already been added.
3632882Svi117747 	 */
3642882Svi117747 	header = sip_search_for_header(msg, SIP_CONTENT_LENGTH, NULL);
3652882Svi117747 	if (header != NULL) {
3662882Svi117747 		/*
3672882Svi117747 		 * Mark the previous header as deleted.
3682882Svi117747 		 */
3692882Svi117747 		header->sip_header_state = SIP_HEADER_DELETED;
3702882Svi117747 		header->sip_hdr_sipmsg->sip_msg_len -= header->sip_hdr_end -
3712882Svi117747 		    header->sip_hdr_start;
3722882Svi117747 	}
3732882Svi117747 	(void) pthread_mutex_unlock(&msg->sip_msg_mutex);
3742882Svi117747 	ret = sip_add_content_length(msg, msg->sip_msg_content_len);
3752882Svi117747 	if (ret != 0) {
3762882Svi117747 		(void) pthread_mutex_unlock(&msg->sip_msg_mutex);
3772882Svi117747 		return (ret);
3782882Svi117747 	}
3792882Svi117747 	(void) pthread_mutex_lock(&msg->sip_msg_mutex);
3802882Svi117747 	msg->sip_msg_modified = B_FALSE;
3812882Svi117747 
3822882Svi117747 	msg->sip_msg_buf = sip_msg_to_msgbuf((sip_msg_t)msg, &ret);
3832882Svi117747 	if (msg->sip_msg_buf == NULL) {
3842882Svi117747 		(void) pthread_mutex_unlock(&msg->sip_msg_mutex);
3852882Svi117747 		return (ret);
3862882Svi117747 	}
3872882Svi117747 	/*
3882882Svi117747 	 * Once the message has been sent it can not be modified
3892882Svi117747 	 * any furthur as we keep a pointer to it for retransmission
3902882Svi117747 	 */
3912882Svi117747 	msg->sip_msg_cannot_be_modified = B_TRUE;
3922882Svi117747 
3932882Svi117747 	(void) pthread_mutex_unlock(&msg->sip_msg_mutex);
3942882Svi117747 	return (0);
3952882Svi117747 }
3962882Svi117747 
3972882Svi117747 /*
3982882Svi117747  * Copy header values into ptr
3992882Svi117747  */
4002882Svi117747 int
sip_copy_values(char * ptr,_sip_header_t * header)4012882Svi117747 sip_copy_values(char *ptr, _sip_header_t *header)
4022882Svi117747 {
4032882Svi117747 	sip_header_value_t	value;
4042882Svi117747 	int			tlen = 0;
4052882Svi117747 	int			len = 0;
4062882Svi117747 	boolean_t		first = B_TRUE;
4072882Svi117747 	char			*p = ptr;
4082882Svi117747 	char			*s;
4092882Svi117747 	boolean_t		crlf_present = B_FALSE;
4102882Svi117747 
4112882Svi117747 	if (sip_parse_goto_values(header) != 0)
4122882Svi117747 		return (0);
4132882Svi117747 
4142882Svi117747 	len = header->sip_hdr_current - header->sip_hdr_start;
4152882Svi117747 	(void) strncpy(p, header->sip_hdr_start, len);
4162882Svi117747 	tlen += len;
4172882Svi117747 	p += len;
4182882Svi117747 	value = header->sip_hdr_parsed->value;
4192882Svi117747 	while (value != NULL) {
4202882Svi117747 		if (value->value_state != SIP_VALUE_DELETED) {
4212882Svi117747 			crlf_present = B_FALSE;
4222882Svi117747 			len = value->value_end - value->value_start;
4232882Svi117747 			if (first) {
4242882Svi117747 				(void) strncpy(p, value->value_start, len);
4252882Svi117747 				first = B_FALSE;
4262882Svi117747 			} else {
4272882Svi117747 				s = value->value_start;
4282882Svi117747 				while (*s != SIP_COMMA)
4292882Svi117747 					s--;
4302882Svi117747 				len += value->value_start - s;
4312882Svi117747 				(void) strncpy(p, s, len);
4322882Svi117747 			}
4332882Svi117747 			tlen += len;
4342882Svi117747 			p += len;
4352882Svi117747 			s = value->value_end;
4362882Svi117747 			while (s != value->value_start) {
4372882Svi117747 				if (*s == '\r' && strncmp(s, SIP_CRLF,
4382882Svi117747 				    strlen(SIP_CRLF)) == 0) {
4392882Svi117747 					crlf_present = B_TRUE;
4402882Svi117747 					break;
4412882Svi117747 				}
4422882Svi117747 				s--;
4432882Svi117747 			}
4442882Svi117747 		} else {
4452882Svi117747 			if (value->next == NULL && !first && !crlf_present) {
4462882Svi117747 				s = value->value_end;
4472882Svi117747 				while (*s != '\r')
4482882Svi117747 					s--;
4492882Svi117747 				len = value->value_end - s;
4502882Svi117747 				(void) strncpy(p, s, len);
4512882Svi117747 				tlen += len;
4522882Svi117747 				p += len;
4532882Svi117747 			}
4542882Svi117747 		}
4552882Svi117747 		value = value->next;
4562882Svi117747 	}
4572882Svi117747 	return (tlen);
4582882Svi117747 }
4592882Svi117747 
4602882Svi117747 
4612882Svi117747 /*
4622882Svi117747  * Add content (message body) to sip_msg
4632882Svi117747  */
4642882Svi117747 int
sip_add_content(sip_msg_t sip_msg,char * content)4652882Svi117747 sip_add_content(sip_msg_t sip_msg, char *content)
4662882Svi117747 {
4672882Svi117747 	size_t		len;
4682882Svi117747 	sip_content_t	**loc;
4692882Svi117747 	sip_content_t	*msg_content;
4702882Svi117747 	_sip_msg_t	*_sip_msg;
4712882Svi117747 
4722882Svi117747 	if (sip_msg == NULL || content == NULL || strlen(content) == 0)
4732882Svi117747 		return (EINVAL);
4742882Svi117747 	len = strlen(content);
4752882Svi117747 	_sip_msg = (_sip_msg_t *)sip_msg;
4762882Svi117747 	(void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
4772882Svi117747 
4782882Svi117747 	if (_sip_msg->sip_msg_cannot_be_modified) {
4792882Svi117747 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
4802882Svi117747 		return (ENOTSUP);
4812882Svi117747 	}
4822882Svi117747 
4832882Svi117747 	msg_content = calloc(1, sizeof (sip_content_t));
4842882Svi117747 	if (msg_content == NULL) {
4852882Svi117747 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
4862882Svi117747 		return (ENOMEM);
4872882Svi117747 	}
4882882Svi117747 	msg_content->sip_content_start = malloc(strlen(content) + 1);
4892882Svi117747 	if (msg_content->sip_content_start == NULL) {
4902882Svi117747 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
4912882Svi117747 		free(msg_content);
4922882Svi117747 		return (ENOMEM);
4932882Svi117747 	}
4942882Svi117747 	(void) strncpy(msg_content->sip_content_start, content,
4952882Svi117747 	    strlen(content));
4962882Svi117747 	msg_content->sip_content_start[strlen(content)] = '\0';
4972882Svi117747 	msg_content->sip_content_current = msg_content->sip_content_start;
4982882Svi117747 	msg_content->sip_content_end = msg_content->sip_content_start +
4992882Svi117747 	    strlen(msg_content->sip_content_start);
5002882Svi117747 	msg_content->sip_content_allocated = B_TRUE;
5012882Svi117747 
5022882Svi117747 	loc = &_sip_msg->sip_msg_content;
5032882Svi117747 	while (*loc != NULL)
5042882Svi117747 		loc = &((*loc)->sip_content_next);
5052882Svi117747 	*loc = msg_content;
5062882Svi117747 
5072882Svi117747 	_sip_msg->sip_msg_content_len += len;
5082882Svi117747 	_sip_msg->sip_msg_len += len;
5092882Svi117747 	if (_sip_msg->sip_msg_buf != NULL)
5102882Svi117747 		_sip_msg->sip_msg_modified = B_TRUE;
5112882Svi117747 	(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
5122882Svi117747 	return (0);
5132882Svi117747 }
5142882Svi117747 
5152882Svi117747 /*
5162882Svi117747  * Free the message content
5172882Svi117747  */
5182882Svi117747 void
sip_free_content(_sip_msg_t * sip_msg)5192882Svi117747 sip_free_content(_sip_msg_t *sip_msg)
5202882Svi117747 {
5212882Svi117747 	sip_content_t *content;
5222882Svi117747 
5232882Svi117747 	if (sip_msg == NULL)
5242882Svi117747 		return;
5252882Svi117747 	content = sip_msg->sip_msg_content;
5262882Svi117747 	while (content != NULL) {
5272882Svi117747 		sip_content_t *content_tmp;
5282882Svi117747 
5292882Svi117747 		content_tmp = content;
5302882Svi117747 		content = content->sip_content_next;
5312882Svi117747 		if (content_tmp->sip_content_allocated)
5322882Svi117747 			free(content_tmp->sip_content_start);
5332882Svi117747 		free(content_tmp);
5342882Svi117747 	}
5352882Svi117747 	sip_msg->sip_msg_content = NULL;
5362882Svi117747 }
5372882Svi117747 
5382882Svi117747 
5392882Svi117747 /*
5402882Svi117747  * Add a response line to sip_response
5412882Svi117747  */
5422882Svi117747 int
sip_add_response_line(sip_msg_t sip_response,int response,char * response_code)5432882Svi117747 sip_add_response_line(sip_msg_t sip_response, int response, char *response_code)
5442882Svi117747 {
5452882Svi117747 	_sip_header_t	*new_header;
5462882Svi117747 	int		header_size;
5472882Svi117747 	_sip_msg_t	*_sip_response;
5482882Svi117747 	int		ret;
5492882Svi117747 
5502882Svi117747 	if (sip_response == NULL || response < 0 || response_code == NULL)
5512882Svi117747 		return (EINVAL);
5522882Svi117747 	_sip_response = (_sip_msg_t *)sip_response;
5532882Svi117747 	(void) pthread_mutex_lock(&_sip_response->sip_msg_mutex);
5542882Svi117747 	if (_sip_response->sip_msg_cannot_be_modified) {
5552882Svi117747 		(void) pthread_mutex_unlock(&_sip_response->sip_msg_mutex);
5562882Svi117747 		return (ENOTSUP);
5572882Svi117747 	}
5582882Svi117747 	header_size = strlen(SIP_VERSION) + SIP_SPACE_LEN +
5592882Svi117747 	    SIP_SIZE_OF_STATUS_CODE + SIP_SPACE_LEN + strlen(response_code) +
5602882Svi117747 	    strlen(SIP_CRLF);
5612882Svi117747 
5622882Svi117747 	new_header = sip_new_header(header_size);
5632882Svi117747 	if (new_header == NULL) {
5642882Svi117747 		(void) pthread_mutex_unlock(&_sip_response->sip_msg_mutex);
5652882Svi117747 		return (ENOMEM);
5662882Svi117747 	}
5672882Svi117747 	new_header->sip_hdr_sipmsg = _sip_response;
5682882Svi117747 
5692882Svi117747 	(void) snprintf(new_header->sip_hdr_start, header_size + 1,
5702882Svi117747 	    SIP_RESPONSE, SIP_VERSION, response, response_code, SIP_CRLF);
5712882Svi117747 
5722882Svi117747 	new_header->sip_hdr_next = _sip_response->sip_msg_start_line;
5732882Svi117747 	_sip_response->sip_msg_start_line = new_header;
5742882Svi117747 	_sip_response->sip_msg_len += header_size;
5752882Svi117747 	ret = sip_parse_first_line(_sip_response->sip_msg_start_line,
5762882Svi117747 	    &_sip_response->sip_msg_req_res);
5772882Svi117747 	if (_sip_response->sip_msg_buf != NULL)
5782882Svi117747 		_sip_response->sip_msg_modified = B_TRUE;
5792882Svi117747 	(void) pthread_mutex_unlock(&_sip_response->sip_msg_mutex);
5802882Svi117747 	return (ret);
5812882Svi117747 }
5822882Svi117747 
5832882Svi117747 /*
5842882Svi117747  * create a response based on the sip_request.
5852882Svi117747  * Copies Call-ID, CSeq, From, To and Via headers from the request.
5862882Svi117747  */
5872882Svi117747 sip_msg_t
sip_create_response(sip_msg_t sip_request,int response,char * response_code,char * totag,char * mycontact)5882882Svi117747 sip_create_response(sip_msg_t sip_request, int response, char *response_code,
5892882Svi117747     char *totag, char *mycontact)
5902882Svi117747 {
5912882Svi117747 	_sip_msg_t	*new_msg;
5922882Svi117747 	_sip_msg_t	*_sip_request;
5932882Svi117747 	boolean_t	ttag_present;
5942882Svi117747 
5952882Svi117747 	if (sip_request == NULL || response_code == NULL)
5962882Svi117747 		return (NULL);
5972882Svi117747 
5982882Svi117747 	ttag_present =  sip_get_to_tag(sip_request, NULL) != NULL;
5992882Svi117747 
6002882Svi117747 	new_msg = (_sip_msg_t *)sip_new_msg();
6012882Svi117747 	if (new_msg == NULL)
6022882Svi117747 		return (NULL);
6032882Svi117747 	_sip_request = (_sip_msg_t *)sip_request;
6042882Svi117747 
6052882Svi117747 	(void) pthread_mutex_lock(&_sip_request->sip_msg_mutex);
6062882Svi117747 
6072882Svi117747 	/*
6082882Svi117747 	 * Add response line.
6092882Svi117747 	 */
6102882Svi117747 	if (sip_add_response_line(new_msg, response, response_code) != 0)
6112882Svi117747 		goto error;
6122882Svi117747 
6132882Svi117747 	/*
6142882Svi117747 	 * Copy Via headers
6152882Svi117747 	 */
6162882Svi117747 	if (_sip_find_and_copy_all_header(_sip_request, new_msg, SIP_VIA) != 0)
6172882Svi117747 		goto error;
6182882Svi117747 
6192882Svi117747 	/*
6202882Svi117747 	 * Copy From header.
6212882Svi117747 	 */
6222882Svi117747 	if (_sip_find_and_copy_header(_sip_request, new_msg, SIP_FROM,
6232882Svi117747 	    NULL, B_FALSE)) {
6242882Svi117747 		goto error;
6252882Svi117747 	}
6262882Svi117747 	/*
6272882Svi117747 	 * Copy To header. If To tag is present, copy it, if not then
6282882Svi117747 	 * add one if the repsonse is not provisional.
6292882Svi117747 	 */
6302882Svi117747 	if (ttag_present || (totag == NULL && response == SIP_TRYING)) {
6312882Svi117747 		if (_sip_find_and_copy_header(_sip_request, new_msg, SIP_TO,
6322882Svi117747 		    NULL, B_FALSE)) {
6332882Svi117747 			goto error;
6342882Svi117747 		}
6352882Svi117747 	} else {
6362882Svi117747 		char		*xtra_param;
6372882Svi117747 		boolean_t	tag_alloc = B_FALSE;
6382882Svi117747 		int		taglen;
6392882Svi117747 
6402882Svi117747 		if (totag == NULL) {
6412882Svi117747 			totag = sip_guid();
6422882Svi117747 			if (totag == NULL)
6432882Svi117747 				goto error;
6442882Svi117747 			tag_alloc = B_TRUE;
6452882Svi117747 		}
6462882Svi117747 		taglen = strlen(SIP_TAG) + strlen(totag) + 1;
6472882Svi117747 		xtra_param = (char *)malloc(taglen);
6482882Svi117747 		if (xtra_param == NULL) {
6492882Svi117747 			if (tag_alloc)
6502882Svi117747 				free(totag);
6512882Svi117747 			goto error;
6522882Svi117747 		}
6532882Svi117747 		(void) snprintf(xtra_param, taglen, "%s%s", SIP_TAG, totag);
6542882Svi117747 		if (tag_alloc)
6552882Svi117747 			free(totag);
6562882Svi117747 		if (_sip_find_and_copy_header(_sip_request, new_msg,
6572882Svi117747 		    SIP_TO, xtra_param, B_FALSE)) {
6582882Svi117747 			free(xtra_param);
6592882Svi117747 			goto error;
6602882Svi117747 		}
6612882Svi117747 		free(xtra_param);
6622882Svi117747 	}
6632882Svi117747 
6642882Svi117747 	/*
6652882Svi117747 	 * Copy Call-ID header.
6662882Svi117747 	 */
6672882Svi117747 	if (_sip_find_and_copy_header(_sip_request, new_msg, SIP_CALL_ID, NULL,
6682882Svi117747 	    B_FALSE)) {
6692882Svi117747 		goto error;
6702882Svi117747 	}
6712882Svi117747 	/*
6722882Svi117747 	 * Copy CSEQ header
6732882Svi117747 	 */
6742882Svi117747 	if (_sip_find_and_copy_header(_sip_request, new_msg, SIP_CSEQ, NULL,
6752882Svi117747 	    B_FALSE)) {
6762882Svi117747 		goto error;
6772882Svi117747 	}
6782882Svi117747 	/*
6792882Svi117747 	 * Copy RECORD-ROUTE header, if present.
6802882Svi117747 	 */
6812882Svi117747 	if (sip_search_for_header(_sip_request, SIP_RECORD_ROUTE, NULL) !=
6822882Svi117747 	    NULL) {
6832882Svi117747 		if (_sip_find_and_copy_all_header(_sip_request, new_msg,
6842882Svi117747 		    SIP_RECORD_ROUTE) != 0) {
6852882Svi117747 			goto error;
6862882Svi117747 		}
6872882Svi117747 	}
6882882Svi117747 	if (mycontact != NULL) {
6892882Svi117747 		if (sip_add_contact(new_msg, NULL, mycontact, B_FALSE,
6902882Svi117747 		    NULL) != 0) {
6912882Svi117747 			goto error;
6922882Svi117747 		}
6932882Svi117747 	}
6942882Svi117747 	(void) pthread_mutex_unlock(&_sip_request->sip_msg_mutex);
6952882Svi117747 	return ((sip_msg_t)new_msg);
6962882Svi117747 error:
6972882Svi117747 	sip_free_msg((sip_msg_t)new_msg);
6982882Svi117747 	(void) pthread_mutex_unlock(&_sip_request->sip_msg_mutex);
6992882Svi117747 	return (NULL);
7002882Svi117747 }
7012882Svi117747 
7022882Svi117747 /*
7032882Svi117747  * NON OK ACK : MUST contain values for the Call-ID, From, and Request-URI
7042882Svi117747  * that are equal to the values of those header fields in the orig request
7052882Svi117747  * passed to the transport. The To header field in the ACK MUST equal the To
7062882Svi117747  * header field in the response being acknowledged. The ACK MUST contain the
7072882Svi117747  * top Via header field of the original request.  The CSeq header field in
7082882Svi117747  * the ACK MUST contain the same value for the sequence number as was
7092882Svi117747  * present in the original request, but the method parameter MUST be equal
7102882Svi117747  * to "ACK".
7112882Svi117747  */
7122882Svi117747 int
sip_create_nonOKack(sip_msg_t request,sip_msg_t response,sip_msg_t ack_msg)7132882Svi117747 sip_create_nonOKack(sip_msg_t request, sip_msg_t response, sip_msg_t ack_msg)
7142882Svi117747 {
7152882Svi117747 	int		seqno;
7162882Svi117747 	char		*uri;
7172882Svi117747 	_sip_msg_t	*_request;
7182882Svi117747 	_sip_msg_t	*_response;
7192882Svi117747 	_sip_msg_t	*_ack_msg;
7202882Svi117747 	int		ret;
7212882Svi117747 
7222882Svi117747 	if (request == NULL || response == NULL || ack_msg == NULL ||
7232882Svi117747 	    request == ack_msg) {
7242882Svi117747 		return (EINVAL);
7252882Svi117747 	}
7262882Svi117747 	_request = (_sip_msg_t *)request;
7272882Svi117747 	_response = (_sip_msg_t *)response;
7282882Svi117747 	_ack_msg = (_sip_msg_t *)ack_msg;
7292882Svi117747 
7302882Svi117747 	(void) pthread_mutex_lock(&_request->sip_msg_mutex);
7312882Svi117747 	if (_request->sip_msg_req_res == NULL) {
7322882Svi117747 		if ((ret = sip_parse_first_line(_request->sip_msg_start_line,
7332882Svi117747 		    &_request->sip_msg_req_res)) != 0) {
7342882Svi117747 			(void) pthread_mutex_unlock(&_request->sip_msg_mutex);
7352882Svi117747 			return (ret);
7362882Svi117747 		}
7372882Svi117747 	}
7382882Svi117747 	if (_request->sip_msg_req_res->U.sip_request.sip_request_uri.
7392882Svi117747 	    sip_str_ptr == NULL) {
7402882Svi117747 		(void) pthread_mutex_unlock(&_request->sip_msg_mutex);
7412882Svi117747 		return (EINVAL);
7422882Svi117747 	}
7432882Svi117747 	uri = (char *)malloc(_request->sip_msg_req_res->U.sip_request.
7442882Svi117747 	    sip_request_uri.sip_str_len + 1);
7452882Svi117747 	if (uri == NULL) {
7462882Svi117747 		(void) pthread_mutex_unlock(&_request->sip_msg_mutex);
7472882Svi117747 		return (EINVAL);
7482882Svi117747 	}
7492882Svi117747 	(void) strncpy(uri,
7502882Svi117747 	    _request->sip_msg_req_res->U.sip_request.sip_request_uri.
7512882Svi117747 	    sip_str_ptr, _request->sip_msg_req_res->U.sip_request.
7522882Svi117747 	    sip_request_uri.sip_str_len);
7532882Svi117747 	uri[_request->sip_msg_req_res->U.sip_request.
7542882Svi117747 	    sip_request_uri.sip_str_len] = '\0';
7552882Svi117747 	if ((ret = sip_add_request_line(_ack_msg, ACK, uri)) != 0) {
7562882Svi117747 		(void) pthread_mutex_unlock(&_request->sip_msg_mutex);
7572882Svi117747 		return (ret);
7582882Svi117747 	}
7592882Svi117747 	free(uri);
7602882Svi117747 	if ((ret = _sip_find_and_copy_header(_request, _ack_msg, SIP_VIA,
7612882Svi117747 	    NULL, B_TRUE)) != 0) {
7622882Svi117747 		(void) pthread_mutex_unlock(&_request->sip_msg_mutex);
7632882Svi117747 		return (ret);
7642882Svi117747 	}
7652882Svi117747 	(void) _sip_find_and_copy_header(_request, _ack_msg,
7662882Svi117747 	    SIP_MAX_FORWARDS, NULL, B_TRUE);
7672882Svi117747 
7682882Svi117747 	(void) pthread_mutex_lock(&_response->sip_msg_mutex);
7692882Svi117747 	if ((ret = _sip_find_and_copy_header(_response, _ack_msg, SIP_TO,
7702882Svi117747 	    NULL, B_TRUE)) != 0) {
7712882Svi117747 		(void) pthread_mutex_unlock(&_response->sip_msg_mutex);
7722882Svi117747 		return (ret);
7732882Svi117747 	}
7742882Svi117747 	(void) pthread_mutex_unlock(&_response->sip_msg_mutex);
7752882Svi117747 	if ((ret = _sip_find_and_copy_header(_request, _ack_msg, SIP_FROM,
7762882Svi117747 	    NULL, B_TRUE)) != 0) {
7772882Svi117747 		(void) pthread_mutex_unlock(&_request->sip_msg_mutex);
7782882Svi117747 		return (ret);
7792882Svi117747 	}
7802882Svi117747 	if ((ret = _sip_find_and_copy_header(_request, _ack_msg, SIP_CALL_ID,
7812882Svi117747 	    NULL, B_TRUE)) != 0) {
7822882Svi117747 		(void) pthread_mutex_unlock(&_request->sip_msg_mutex);
7832882Svi117747 		return (ret);
7842882Svi117747 	}
7852882Svi117747 	(void) pthread_mutex_unlock(&_request->sip_msg_mutex);
7862882Svi117747 	seqno = sip_get_callseq_num(_request, &ret);
7872882Svi117747 	if (ret != 0)
7882882Svi117747 		return (ret);
7892882Svi117747 	if ((ret = sip_add_cseq(_ack_msg, ACK, seqno)) != 0)
7902882Svi117747 		return (ret);
7912882Svi117747 	if ((ret = sip_adjust_msgbuf(_ack_msg)) != 0)
7922882Svi117747 		return (ret);
7932882Svi117747 	return (0);
7942882Svi117747 }
7952882Svi117747 
7962882Svi117747 /*
7972882Svi117747  * This is a 2XX ACK, for others ACK is constructed differently,
7982882Svi117747  * esp. the branch id is retained.
7992882Svi117747  */
8002882Svi117747 int
sip_create_OKack(sip_msg_t response,sip_msg_t ack_msg,char * transport,char * sent_by,int sent_by_port,char * via_params)8012882Svi117747 sip_create_OKack(sip_msg_t response, sip_msg_t ack_msg, char *transport,
8022882Svi117747     char *sent_by, int sent_by_port, char *via_params)
8032882Svi117747 {
8042882Svi117747 	int			seqno;
8052882Svi117747 	char			*uri;
8062882Svi117747 	sip_parsed_header_t	*parsed_header;
8072882Svi117747 	sip_hdr_value_t		*contact_value;
8082882Svi117747 	_sip_header_t		*header;
8092882Svi117747 	_sip_msg_t		*_response;
8102882Svi117747 	_sip_msg_t		*_ack_msg;
8112882Svi117747 	int			ret;
8122882Svi117747 
8132882Svi117747 	if (response == NULL || response == NULL || transport == NULL)
8142882Svi117747 		return (EINVAL);
8152882Svi117747 	_response = (_sip_msg_t *)response;
8162882Svi117747 	_ack_msg = (_sip_msg_t *)ack_msg;
8172882Svi117747 
8182882Svi117747 	/*
8192882Svi117747 	 * Get URI from the response, Contact field
8202882Svi117747 	 */
8212882Svi117747 	(void) pthread_mutex_lock(&_response->sip_msg_mutex);
8222882Svi117747 	if ((header = sip_search_for_header(_response, SIP_CONTACT,
8232882Svi117747 	    NULL)) == NULL) {
8242882Svi117747 		(void) pthread_mutex_unlock(&_response->sip_msg_mutex);
8252882Svi117747 		return (EINVAL);
8262882Svi117747 	}
8272882Svi117747 	if ((ret = sip_parse_cftr_header(header, (void *)&parsed_header)) !=
8282882Svi117747 	    0) {
8292882Svi117747 		(void) pthread_mutex_unlock(&_response->sip_msg_mutex);
8302882Svi117747 		return (ret);
8312882Svi117747 	}
8322882Svi117747 	contact_value = (sip_hdr_value_t *)parsed_header->value;
8332882Svi117747 	if (contact_value->cftr_uri.sip_str_ptr == NULL) {
8342882Svi117747 		(void) pthread_mutex_unlock(&_response->sip_msg_mutex);
8352882Svi117747 		return (EINVAL);
8362882Svi117747 	}
8372882Svi117747 	uri = (char *)malloc(contact_value->cftr_uri.sip_str_len + 1);
8382882Svi117747 	if (uri == NULL) {
8392882Svi117747 		(void) pthread_mutex_unlock(&_response->sip_msg_mutex);
8402882Svi117747 		return (ENOMEM);
8412882Svi117747 	}
8422882Svi117747 	(void) strncpy(uri, contact_value->cftr_uri.sip_str_ptr,
8432882Svi117747 	    contact_value->cftr_uri.sip_str_len);
8442882Svi117747 	uri[contact_value->cftr_uri.sip_str_len] = '\0';
8452882Svi117747 	if ((ret = sip_add_request_line(_ack_msg, ACK, uri)) != 0) {
8462882Svi117747 		(void) pthread_mutex_unlock(&_response->sip_msg_mutex);
8472882Svi117747 		return (ret);
8482882Svi117747 	}
8492882Svi117747 	free(uri);
8502882Svi117747 	if ((ret = sip_add_via(_ack_msg, transport, sent_by, sent_by_port,
8512882Svi117747 	    via_params)) != 0) {
8522882Svi117747 		(void) pthread_mutex_unlock(&_response->sip_msg_mutex);
8532882Svi117747 		return (ret);
8542882Svi117747 	}
8552882Svi117747 
8562882Svi117747 	if ((ret = _sip_find_and_copy_header(_response, _ack_msg, SIP_TO,
8572882Svi117747 	    NULL, B_TRUE)) != 0) {
8582882Svi117747 		(void) pthread_mutex_unlock(&_response->sip_msg_mutex);
8592882Svi117747 		return (ret);
8602882Svi117747 	}
8612882Svi117747 	if ((ret = _sip_find_and_copy_header(_response, _ack_msg, SIP_FROM,
8622882Svi117747 	    NULL, B_TRUE)) != 0) {
8632882Svi117747 		(void) pthread_mutex_unlock(&_response->sip_msg_mutex);
8642882Svi117747 		return (ret);
8652882Svi117747 	}
8662882Svi117747 	if ((ret = _sip_find_and_copy_header(_response, _ack_msg, SIP_CALL_ID,
8672882Svi117747 	    NULL, B_TRUE)) != 0) {
8682882Svi117747 		(void) pthread_mutex_unlock(&_response->sip_msg_mutex);
8692882Svi117747 		return (ret);
8702882Svi117747 	}
8712882Svi117747 	/*
8722882Svi117747 	 * Copy Max-Forward if present
8732882Svi117747 	 */
8742882Svi117747 	if (sip_search_for_header(_response, SIP_MAX_FORWARDS, NULL) != NULL) {
8752882Svi117747 		if ((ret = _sip_find_and_copy_header(_response, _ack_msg,
8762882Svi117747 		    SIP_MAX_FORWARDS, NULL, B_TRUE)) != 0) {
8772882Svi117747 			(void) pthread_mutex_unlock(&_response->sip_msg_mutex);
8782882Svi117747 			return (ret);
8792882Svi117747 		}
8802882Svi117747 	}
8812882Svi117747 	(void) pthread_mutex_unlock(&_response->sip_msg_mutex);
8822882Svi117747 	seqno = sip_get_callseq_num(_response, &ret);
8832882Svi117747 	if (ret != 0)
8842882Svi117747 		return (ret);
8852882Svi117747 	if ((ret = sip_add_cseq(_ack_msg, ACK, seqno)) != 0)
8862882Svi117747 		return (ret);
8872882Svi117747 
8882882Svi117747 	return (0);
8892882Svi117747 }
8902882Svi117747 
8912882Svi117747 /*
8922882Svi117747  * Request-Line   =  Method SP Request-URI SP SIP-Version CRLF
8932882Svi117747  */
8942882Svi117747 int
sip_add_request_line(sip_msg_t sip_request,sip_method_t method,char * request_uri)8952882Svi117747 sip_add_request_line(sip_msg_t sip_request, sip_method_t method,
8962882Svi117747     char *request_uri)
8972882Svi117747 {
8982882Svi117747 	_sip_header_t	*new_header;
8992882Svi117747 	int		 header_size;
9002882Svi117747 	_sip_msg_t	*_sip_request;
9012882Svi117747 
9022882Svi117747 	if (method < INVITE || method >= MAX_SIP_METHODS ||
9032882Svi117747 	    request_uri == NULL || sip_request == NULL) {
9042882Svi117747 		return (EINVAL);
9052882Svi117747 	}
9062882Svi117747 
9072882Svi117747 	_sip_request = (_sip_msg_t *)sip_request;
9082882Svi117747 	(void) pthread_mutex_lock(&_sip_request->sip_msg_mutex);
9092882Svi117747 	if (_sip_request->sip_msg_cannot_be_modified) {
9102882Svi117747 		(void) pthread_mutex_unlock(&_sip_request->sip_msg_mutex);
9112882Svi117747 		return (ENOTSUP);
9122882Svi117747 	}
9132882Svi117747 
9142882Svi117747 	header_size = strlen(sip_methods[method].name) + SIP_SPACE_LEN +
9152882Svi117747 	    strlen(request_uri) + SIP_SPACE_LEN + strlen(SIP_VERSION) +
9162882Svi117747 	    strlen(SIP_CRLF);
9172882Svi117747 
9182882Svi117747 	new_header = sip_new_header(header_size);
9192882Svi117747 	if (new_header == NULL) {
9202882Svi117747 		(void) pthread_mutex_unlock(&_sip_request->sip_msg_mutex);
9212882Svi117747 		return (ENOMEM);
9222882Svi117747 	}
9232882Svi117747 	new_header->sip_hdr_sipmsg = _sip_request;
9242882Svi117747 
9252882Svi117747 	(void) snprintf(new_header->sip_hdr_start, header_size + 1,
9262882Svi117747 	    "%s %s %s%s", sip_methods[method].name, request_uri,
9272882Svi117747 	    SIP_VERSION, SIP_CRLF);
9282882Svi117747 
9292882Svi117747 	new_header->sip_hdr_next = _sip_request->sip_msg_start_line;
9302882Svi117747 	_sip_request->sip_msg_start_line = new_header;
9312882Svi117747 	_sip_request->sip_msg_len += header_size;
9322882Svi117747 	(void) sip_parse_first_line(_sip_request->sip_msg_start_line,
9332882Svi117747 	    &_sip_request->sip_msg_req_res);
9342882Svi117747 	if (_sip_request->sip_msg_buf != NULL)
9352882Svi117747 		_sip_request->sip_msg_modified = B_TRUE;
9362882Svi117747 	(void) pthread_mutex_unlock(&_sip_request->sip_msg_mutex);
9372882Svi117747 	return (0);
9382882Svi117747 }
939