1*2882Svi117747 /*
2*2882Svi117747  * CDDL HEADER START
3*2882Svi117747  *
4*2882Svi117747  * The contents of this file are subject to the terms of the
5*2882Svi117747  * Common Development and Distribution License (the "License").
6*2882Svi117747  * You may not use this file except in compliance with the License.
7*2882Svi117747  *
8*2882Svi117747  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*2882Svi117747  * or http://www.opensolaris.org/os/licensing.
10*2882Svi117747  * See the License for the specific language governing permissions
11*2882Svi117747  * and limitations under the License.
12*2882Svi117747  *
13*2882Svi117747  * When distributing Covered Code, include this CDDL HEADER in each
14*2882Svi117747  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*2882Svi117747  * If applicable, add the following below this CDDL HEADER, with the
16*2882Svi117747  * fields enclosed by brackets "[]" replaced with your own identifying
17*2882Svi117747  * information: Portions Copyright [yyyy] [name of copyright owner]
18*2882Svi117747  *
19*2882Svi117747  * CDDL HEADER END
20*2882Svi117747  */
21*2882Svi117747 
22*2882Svi117747 /*
23*2882Svi117747  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
24*2882Svi117747  * Use is subject to license terms.
25*2882Svi117747  */
26*2882Svi117747 
27*2882Svi117747 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*2882Svi117747 
29*2882Svi117747 #include "sip_parse_uri.h"
30*2882Svi117747 #include "sip_msg.h"
31*2882Svi117747 #include "sip_miscdefs.h"
32*2882Svi117747 #include "sip_parse_generic.h"
33*2882Svi117747 
34*2882Svi117747 /*
35*2882Svi117747  * Response consists of SIP version, response code, response phrase and CRLF.
36*2882Svi117747  */
37*2882Svi117747 #define	SIP_RESPONSE	"%s %d %s%s"
38*2882Svi117747 
39*2882Svi117747 void sip_free_content(_sip_msg_t *);
40*2882Svi117747 
41*2882Svi117747 /*
42*2882Svi117747  * Allocate a new sip msg struct.
43*2882Svi117747  */
44*2882Svi117747 sip_msg_t
45*2882Svi117747 sip_new_msg()
46*2882Svi117747 {
47*2882Svi117747 	_sip_msg_t *sip_msg;
48*2882Svi117747 
49*2882Svi117747 	sip_msg = calloc(1, sizeof (_sip_msg_t));
50*2882Svi117747 	if (sip_msg != NULL) {
51*2882Svi117747 		sip_msg->sip_msg_ref_cnt = 1;
52*2882Svi117747 		(void) pthread_mutex_init(&sip_msg->sip_msg_mutex, NULL);
53*2882Svi117747 	}
54*2882Svi117747 	return ((sip_msg_t)sip_msg);
55*2882Svi117747 }
56*2882Svi117747 
57*2882Svi117747 /*
58*2882Svi117747  * Free all resources. The lock is taken by SIP_MSG_REFCNT_DECR. The
59*2882Svi117747  * thread that decrements the last refcount should take care that
60*2882Svi117747  * the message is not accessible to other threads before doing so.
61*2882Svi117747  * Else, if the message is still accessible to others, it is
62*2882Svi117747  * possible that the other thread could be waiting to take the
63*2882Svi117747  * lock when we proceed to destroy it.
64*2882Svi117747  */
65*2882Svi117747 void
66*2882Svi117747 sip_destroy_msg(_sip_msg_t *_sip_msg)
67*2882Svi117747 {
68*2882Svi117747 #ifdef	__solaris__
69*2882Svi117747 	assert(mutex_held(&_sip_msg->sip_msg_mutex));
70*2882Svi117747 #endif
71*2882Svi117747 	(void) sip_delete_start_line_locked(_sip_msg);
72*2882Svi117747 	assert(_sip_msg->sip_msg_ref_cnt == 0);
73*2882Svi117747 	sip_delete_all_headers((sip_msg_t)_sip_msg);
74*2882Svi117747 	sip_free_content(_sip_msg);
75*2882Svi117747 	if (_sip_msg->sip_msg_buf != NULL)
76*2882Svi117747 		free(_sip_msg->sip_msg_buf);
77*2882Svi117747 
78*2882Svi117747 	if (_sip_msg->sip_msg_old_buf != NULL)
79*2882Svi117747 		free(_sip_msg->sip_msg_old_buf);
80*2882Svi117747 
81*2882Svi117747 	while (_sip_msg->sip_msg_req_res != NULL) {
82*2882Svi117747 		sip_message_type_t	*sip_msg_type_ptr;
83*2882Svi117747 
84*2882Svi117747 		sip_msg_type_ptr = _sip_msg->sip_msg_req_res->sip_next;
85*2882Svi117747 		if (_sip_msg->sip_msg_req_res->is_request) {
86*2882Svi117747 			sip_request_t	*reqline;
87*2882Svi117747 
88*2882Svi117747 			reqline = &_sip_msg->sip_msg_req_res->U.sip_request;
89*2882Svi117747 			if (reqline->sip_parse_uri != NULL) {
90*2882Svi117747 				sip_free_parsed_uri(reqline->sip_parse_uri);
91*2882Svi117747 				reqline->sip_parse_uri = NULL;
92*2882Svi117747 			}
93*2882Svi117747 		}
94*2882Svi117747 		free(_sip_msg->sip_msg_req_res);
95*2882Svi117747 		_sip_msg->sip_msg_req_res = sip_msg_type_ptr;
96*2882Svi117747 	}
97*2882Svi117747 	(void) pthread_mutex_destroy(&_sip_msg->sip_msg_mutex);
98*2882Svi117747 	free(_sip_msg);
99*2882Svi117747 }
100*2882Svi117747 
101*2882Svi117747 /*
102*2882Svi117747  * Free a sip msg struct.
103*2882Svi117747  */
104*2882Svi117747 void
105*2882Svi117747 sip_free_msg(sip_msg_t sip_msg)
106*2882Svi117747 {
107*2882Svi117747 	if (sip_msg == NULL)
108*2882Svi117747 		return;
109*2882Svi117747 
110*2882Svi117747 	SIP_MSG_REFCNT_DECR((_sip_msg_t *)sip_msg);
111*2882Svi117747 }
112*2882Svi117747 
113*2882Svi117747 /*
114*2882Svi117747  * Hold a sip msg struct.
115*2882Svi117747  */
116*2882Svi117747 void
117*2882Svi117747 sip_hold_msg(sip_msg_t sip_msg)
118*2882Svi117747 {
119*2882Svi117747 
120*2882Svi117747 	if (sip_msg == NULL)
121*2882Svi117747 		return;
122*2882Svi117747 
123*2882Svi117747 	SIP_MSG_REFCNT_INCR((_sip_msg_t *)sip_msg);
124*2882Svi117747 }
125*2882Svi117747 
126*2882Svi117747 /*
127*2882Svi117747  * Clone a message
128*2882Svi117747  */
129*2882Svi117747 sip_msg_t
130*2882Svi117747 sip_clone_msg(sip_msg_t sip_msg)
131*2882Svi117747 {
132*2882Svi117747 	_sip_msg_t	*new_msg;
133*2882Svi117747 	_sip_msg_t	*_sip_msg;
134*2882Svi117747 	sip_content_t	*sip_content;
135*2882Svi117747 	sip_content_t	*msg_content;
136*2882Svi117747 	sip_content_t	*new_content = NULL;
137*2882Svi117747 	int		len;
138*2882Svi117747 
139*2882Svi117747 	if (sip_msg == NULL)
140*2882Svi117747 		return (NULL);
141*2882Svi117747 	new_msg = (_sip_msg_t *)sip_new_msg();
142*2882Svi117747 	if (new_msg == NULL)
143*2882Svi117747 		return (NULL);
144*2882Svi117747 	_sip_msg = (_sip_msg_t *)sip_msg;
145*2882Svi117747 	/*
146*2882Svi117747 	 * Get start line
147*2882Svi117747 	 */
148*2882Svi117747 	if (sip_copy_start_line(_sip_msg, new_msg) != 0) {
149*2882Svi117747 		sip_free_msg((sip_msg_t)new_msg);
150*2882Svi117747 		return (NULL);
151*2882Svi117747 	}
152*2882Svi117747 	if (sip_copy_all_headers(_sip_msg, new_msg) != 0) {
153*2882Svi117747 		sip_free_msg((sip_msg_t)new_msg);
154*2882Svi117747 		return (NULL);
155*2882Svi117747 	}
156*2882Svi117747 	(void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
157*2882Svi117747 	sip_content = _sip_msg->sip_msg_content;
158*2882Svi117747 	while (sip_content != NULL) {
159*2882Svi117747 		msg_content = calloc(1, sizeof (sip_content_t));
160*2882Svi117747 		if (msg_content == NULL) {
161*2882Svi117747 			sip_free_msg((sip_msg_t)new_msg);
162*2882Svi117747 			(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
163*2882Svi117747 			return (NULL);
164*2882Svi117747 		}
165*2882Svi117747 		len = sip_content->sip_content_end -
166*2882Svi117747 		    sip_content->sip_content_start;
167*2882Svi117747 		msg_content->sip_content_start = malloc(len + 1);
168*2882Svi117747 		if (msg_content->sip_content_start == NULL) {
169*2882Svi117747 			sip_free_msg((sip_msg_t)new_msg);
170*2882Svi117747 			(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
171*2882Svi117747 			return (NULL);
172*2882Svi117747 		}
173*2882Svi117747 		(void) strncpy(msg_content->sip_content_start,
174*2882Svi117747 		    sip_content->sip_content_start, len);
175*2882Svi117747 		msg_content->sip_content_start[len] = '\0';
176*2882Svi117747 		msg_content->sip_content_current =
177*2882Svi117747 		    msg_content->sip_content_start;
178*2882Svi117747 		msg_content->sip_content_end =  msg_content->sip_content_start +
179*2882Svi117747 		    len;
180*2882Svi117747 		msg_content->sip_content_allocated = B_TRUE;
181*2882Svi117747 		new_msg->sip_msg_content_len += len;
182*2882Svi117747 		new_msg->sip_msg_len += len;
183*2882Svi117747 		if (new_msg->sip_msg_content == NULL)
184*2882Svi117747 			new_msg->sip_msg_content = msg_content;
185*2882Svi117747 		else
186*2882Svi117747 			new_content->sip_content_next = msg_content;
187*2882Svi117747 		new_content = msg_content;
188*2882Svi117747 		sip_content = sip_content->sip_content_next;
189*2882Svi117747 	}
190*2882Svi117747 	(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
191*2882Svi117747 	/*
192*2882Svi117747 	 * Since this is a new message, no threads should be referring
193*2882Svi117747 	 * to this, so it is not necessary to take the lock, however,
194*2882Svi117747 	 * since sip_msg_to_msgbuf() expects the lock to be held, we'll
195*2882Svi117747 	 * take it here.
196*2882Svi117747 	 */
197*2882Svi117747 	(void) pthread_mutex_lock(&new_msg->sip_msg_mutex);
198*2882Svi117747 	new_msg->sip_msg_buf = sip_msg_to_msgbuf((sip_msg_t)new_msg, NULL);
199*2882Svi117747 	if (new_msg->sip_msg_buf == NULL) {
200*2882Svi117747 		(void) pthread_mutex_unlock(&new_msg->sip_msg_mutex);
201*2882Svi117747 		sip_free_msg((sip_msg_t)new_msg);
202*2882Svi117747 		return (NULL);
203*2882Svi117747 	}
204*2882Svi117747 	new_msg->sip_msg_cannot_be_modified = B_TRUE;
205*2882Svi117747 	(void) pthread_mutex_unlock(&new_msg->sip_msg_mutex);
206*2882Svi117747 
207*2882Svi117747 	return ((sip_msg_t)new_msg);
208*2882Svi117747 }
209*2882Svi117747 
210*2882Svi117747 /*
211*2882Svi117747  * Return the SIP message as a string. Caller frees the string
212*2882Svi117747  */
213*2882Svi117747 char *
214*2882Svi117747 sip_msg_to_str(sip_msg_t sip_msg, int *error)
215*2882Svi117747 {
216*2882Svi117747 	_sip_msg_t	*msg;
217*2882Svi117747 	char		*msgstr;
218*2882Svi117747 
219*2882Svi117747 	if (sip_msg == NULL) {
220*2882Svi117747 		if (error != NULL)
221*2882Svi117747 			*error = EINVAL;
222*2882Svi117747 		return (NULL);
223*2882Svi117747 	}
224*2882Svi117747 	msg = (_sip_msg_t *)sip_msg;
225*2882Svi117747 	(void) pthread_mutex_lock(&msg->sip_msg_mutex);
226*2882Svi117747 	msgstr = sip_msg_to_msgbuf(msg, error);
227*2882Svi117747 	(void) pthread_mutex_unlock(&msg->sip_msg_mutex);
228*2882Svi117747 	return (msgstr);
229*2882Svi117747 }
230*2882Svi117747 
231*2882Svi117747 /*
232*2882Svi117747  * Given a message generate a string that includes all the headers and the
233*2882Svi117747  * content.
234*2882Svi117747  */
235*2882Svi117747 char *
236*2882Svi117747 sip_msg_to_msgbuf(_sip_msg_t *msg, int *error)
237*2882Svi117747 {
238*2882Svi117747 	_sip_header_t	*header;
239*2882Svi117747 	int		len = 0;
240*2882Svi117747 	char		*p;
241*2882Svi117747 	char		*e;
242*2882Svi117747 	sip_content_t	*sip_content;
243*2882Svi117747 #ifdef	_DEBUG
244*2882Svi117747 	int		tlen = 0;
245*2882Svi117747 	int		clen = 0;
246*2882Svi117747 #endif
247*2882Svi117747 
248*2882Svi117747 	if (error != NULL)
249*2882Svi117747 		*error = 0;
250*2882Svi117747 
251*2882Svi117747 	if (msg == NULL) {
252*2882Svi117747 		if (error != NULL)
253*2882Svi117747 			*error = EINVAL;
254*2882Svi117747 		return (NULL);
255*2882Svi117747 	}
256*2882Svi117747 #ifdef	__solaris__
257*2882Svi117747 	assert(mutex_held(&msg->sip_msg_mutex));
258*2882Svi117747 #endif
259*2882Svi117747 
260*2882Svi117747 	p = (char *)malloc(msg->sip_msg_len + 1);
261*2882Svi117747 	if (p == NULL) {
262*2882Svi117747 		if (error != 0)
263*2882Svi117747 			*error = ENOMEM;
264*2882Svi117747 		return (NULL);
265*2882Svi117747 	}
266*2882Svi117747 	e = p;
267*2882Svi117747 
268*2882Svi117747 	/*
269*2882Svi117747 	 * Get the start line
270*2882Svi117747 	 */
271*2882Svi117747 	if (msg->sip_msg_start_line != NULL) {
272*2882Svi117747 		len = msg->sip_msg_start_line->sip_hdr_end -
273*2882Svi117747 		    msg->sip_msg_start_line->sip_hdr_start;
274*2882Svi117747 		(void) strncpy(e, msg->sip_msg_start_line->sip_hdr_start, len);
275*2882Svi117747 		e += len;
276*2882Svi117747 #ifdef	_DEBUG
277*2882Svi117747 		tlen += len;
278*2882Svi117747 #endif
279*2882Svi117747 	}
280*2882Svi117747 	header = sip_search_for_header(msg, NULL, NULL);
281*2882Svi117747 	while (header != NULL) {
282*2882Svi117747 		if (header->sip_header_state != SIP_HEADER_DELETED) {
283*2882Svi117747 			if (header->sip_header_state ==
284*2882Svi117747 			    SIP_HEADER_DELETED_VAL) {
285*2882Svi117747 				len = sip_copy_values(e, header);
286*2882Svi117747 			} else {
287*2882Svi117747 				len = header->sip_hdr_end -
288*2882Svi117747 				    header->sip_hdr_start;
289*2882Svi117747 				(void) strncpy(e, header->sip_hdr_start, len);
290*2882Svi117747 			}
291*2882Svi117747 #ifdef	_DEBUG
292*2882Svi117747 			tlen += len;
293*2882Svi117747 			assert(tlen <= msg->sip_msg_len);
294*2882Svi117747 #endif
295*2882Svi117747 		}
296*2882Svi117747 		header = sip_search_for_header(msg, NULL, header);
297*2882Svi117747 		e += len;
298*2882Svi117747 	}
299*2882Svi117747 	sip_content = msg->sip_msg_content;
300*2882Svi117747 	while (sip_content != NULL) {
301*2882Svi117747 		len = sip_content->sip_content_end -
302*2882Svi117747 		    sip_content->sip_content_start;
303*2882Svi117747 #ifdef	_DEBUG
304*2882Svi117747 		clen += len;
305*2882Svi117747 		assert(clen <= msg->sip_msg_content_len);
306*2882Svi117747 		tlen += len;
307*2882Svi117747 		assert(tlen <= msg->sip_msg_len);
308*2882Svi117747 #endif
309*2882Svi117747 		(void) strncpy(e, sip_content->sip_content_start, len);
310*2882Svi117747 		e += len;
311*2882Svi117747 		sip_content = sip_content->sip_content_next;
312*2882Svi117747 	}
313*2882Svi117747 	p[msg->sip_msg_len] = '\0';
314*2882Svi117747 	return (p);
315*2882Svi117747 }
316*2882Svi117747 
317*2882Svi117747 /*
318*2882Svi117747  * This is called just before sending the message to the transport. It
319*2882Svi117747  * creates the sip_msg_buf from the SIP headers.
320*2882Svi117747  */
321*2882Svi117747 int
322*2882Svi117747 sip_adjust_msgbuf(_sip_msg_t *msg)
323*2882Svi117747 {
324*2882Svi117747 	_sip_header_t	*header;
325*2882Svi117747 	int		ret;
326*2882Svi117747 #ifdef	_DEBUG
327*2882Svi117747 	int		tlen = 0;
328*2882Svi117747 	int		clen = 0;
329*2882Svi117747 #endif
330*2882Svi117747 
331*2882Svi117747 	if (msg == NULL)
332*2882Svi117747 		return (EINVAL);
333*2882Svi117747 
334*2882Svi117747 	(void) pthread_mutex_lock(&msg->sip_msg_mutex);
335*2882Svi117747 	if ((msg->sip_msg_buf != NULL) && (!msg->sip_msg_modified)) {
336*2882Svi117747 		/*
337*2882Svi117747 		 * We could just be forwarding the message we
338*2882Svi117747 		 * received.
339*2882Svi117747 		 */
340*2882Svi117747 		(void) pthread_mutex_unlock(&msg->sip_msg_mutex);
341*2882Svi117747 		return (0);
342*2882Svi117747 	}
343*2882Svi117747 
344*2882Svi117747 	/*
345*2882Svi117747 	 * We are sending a new message or a message that we received
346*2882Svi117747 	 * but have modified it. We keep the old
347*2882Svi117747 	 * msgbuf till the message is freed as some
348*2882Svi117747 	 * headers still point to it.
349*2882Svi117747 	 */
350*2882Svi117747 
351*2882Svi117747 	assert(msg->sip_msg_old_buf == NULL);
352*2882Svi117747 	msg->sip_msg_old_buf = msg->sip_msg_buf;
353*2882Svi117747 	/*
354*2882Svi117747 	 * We add the content-length header here, if it has not
355*2882Svi117747 	 * already been added.
356*2882Svi117747 	 */
357*2882Svi117747 	header = sip_search_for_header(msg, SIP_CONTENT_LENGTH, NULL);
358*2882Svi117747 	if (header != NULL) {
359*2882Svi117747 		/*
360*2882Svi117747 		 * Mark the previous header as deleted.
361*2882Svi117747 		 */
362*2882Svi117747 		header->sip_header_state = SIP_HEADER_DELETED;
363*2882Svi117747 		header->sip_hdr_sipmsg->sip_msg_len -= header->sip_hdr_end -
364*2882Svi117747 		    header->sip_hdr_start;
365*2882Svi117747 	}
366*2882Svi117747 	(void) pthread_mutex_unlock(&msg->sip_msg_mutex);
367*2882Svi117747 	ret = sip_add_content_length(msg, msg->sip_msg_content_len);
368*2882Svi117747 	if (ret != 0) {
369*2882Svi117747 		(void) pthread_mutex_unlock(&msg->sip_msg_mutex);
370*2882Svi117747 		return (ret);
371*2882Svi117747 	}
372*2882Svi117747 	(void) pthread_mutex_lock(&msg->sip_msg_mutex);
373*2882Svi117747 	msg->sip_msg_modified = B_FALSE;
374*2882Svi117747 
375*2882Svi117747 	msg->sip_msg_buf = sip_msg_to_msgbuf((sip_msg_t)msg, &ret);
376*2882Svi117747 	if (msg->sip_msg_buf == NULL) {
377*2882Svi117747 		(void) pthread_mutex_unlock(&msg->sip_msg_mutex);
378*2882Svi117747 		return (ret);
379*2882Svi117747 	}
380*2882Svi117747 	/*
381*2882Svi117747 	 * Once the message has been sent it can not be modified
382*2882Svi117747 	 * any furthur as we keep a pointer to it for retransmission
383*2882Svi117747 	 */
384*2882Svi117747 	msg->sip_msg_cannot_be_modified = B_TRUE;
385*2882Svi117747 
386*2882Svi117747 	(void) pthread_mutex_unlock(&msg->sip_msg_mutex);
387*2882Svi117747 	return (0);
388*2882Svi117747 }
389*2882Svi117747 
390*2882Svi117747 /*
391*2882Svi117747  * Copy header values into ptr
392*2882Svi117747  */
393*2882Svi117747 int
394*2882Svi117747 sip_copy_values(char *ptr, _sip_header_t *header)
395*2882Svi117747 {
396*2882Svi117747 	sip_header_value_t	value;
397*2882Svi117747 	int			tlen = 0;
398*2882Svi117747 	int			len = 0;
399*2882Svi117747 	boolean_t		first = B_TRUE;
400*2882Svi117747 	char			*p = ptr;
401*2882Svi117747 	char			*s;
402*2882Svi117747 	boolean_t		crlf_present = B_FALSE;
403*2882Svi117747 
404*2882Svi117747 	if (sip_parse_goto_values(header) != 0)
405*2882Svi117747 		return (0);
406*2882Svi117747 
407*2882Svi117747 	len = header->sip_hdr_current - header->sip_hdr_start;
408*2882Svi117747 	(void) strncpy(p, header->sip_hdr_start, len);
409*2882Svi117747 	tlen += len;
410*2882Svi117747 	p += len;
411*2882Svi117747 	value = header->sip_hdr_parsed->value;
412*2882Svi117747 	while (value != NULL) {
413*2882Svi117747 		if (value->value_state != SIP_VALUE_DELETED) {
414*2882Svi117747 			crlf_present = B_FALSE;
415*2882Svi117747 			len = value->value_end - value->value_start;
416*2882Svi117747 			if (first) {
417*2882Svi117747 				(void) strncpy(p, value->value_start, len);
418*2882Svi117747 				first = B_FALSE;
419*2882Svi117747 			} else {
420*2882Svi117747 				s = value->value_start;
421*2882Svi117747 				while (*s != SIP_COMMA)
422*2882Svi117747 					s--;
423*2882Svi117747 				len += value->value_start - s;
424*2882Svi117747 				(void) strncpy(p, s, len);
425*2882Svi117747 			}
426*2882Svi117747 			tlen += len;
427*2882Svi117747 			p += len;
428*2882Svi117747 			s = value->value_end;
429*2882Svi117747 			while (s != value->value_start) {
430*2882Svi117747 				if (*s == '\r' && strncmp(s, SIP_CRLF,
431*2882Svi117747 				    strlen(SIP_CRLF)) == 0) {
432*2882Svi117747 					crlf_present = B_TRUE;
433*2882Svi117747 					break;
434*2882Svi117747 				}
435*2882Svi117747 				s--;
436*2882Svi117747 			}
437*2882Svi117747 		} else {
438*2882Svi117747 			if (value->next == NULL && !first && !crlf_present) {
439*2882Svi117747 				s = value->value_end;
440*2882Svi117747 				while (*s != '\r')
441*2882Svi117747 					s--;
442*2882Svi117747 				len = value->value_end - s;
443*2882Svi117747 				(void) strncpy(p, s, len);
444*2882Svi117747 				tlen += len;
445*2882Svi117747 				p += len;
446*2882Svi117747 			}
447*2882Svi117747 		}
448*2882Svi117747 		value = value->next;
449*2882Svi117747 	}
450*2882Svi117747 	return (tlen);
451*2882Svi117747 }
452*2882Svi117747 
453*2882Svi117747 
454*2882Svi117747 /*
455*2882Svi117747  * Add content (message body) to sip_msg
456*2882Svi117747  */
457*2882Svi117747 int
458*2882Svi117747 sip_add_content(sip_msg_t sip_msg, char *content)
459*2882Svi117747 {
460*2882Svi117747 	size_t		len;
461*2882Svi117747 	sip_content_t	**loc;
462*2882Svi117747 	sip_content_t	*msg_content;
463*2882Svi117747 	_sip_msg_t	*_sip_msg;
464*2882Svi117747 
465*2882Svi117747 	if (sip_msg == NULL || content == NULL || strlen(content) == 0)
466*2882Svi117747 		return (EINVAL);
467*2882Svi117747 	len = strlen(content);
468*2882Svi117747 	_sip_msg = (_sip_msg_t *)sip_msg;
469*2882Svi117747 	(void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
470*2882Svi117747 
471*2882Svi117747 	if (_sip_msg->sip_msg_cannot_be_modified) {
472*2882Svi117747 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
473*2882Svi117747 		return (ENOTSUP);
474*2882Svi117747 	}
475*2882Svi117747 
476*2882Svi117747 	msg_content = calloc(1, sizeof (sip_content_t));
477*2882Svi117747 	if (msg_content == NULL) {
478*2882Svi117747 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
479*2882Svi117747 		return (ENOMEM);
480*2882Svi117747 	}
481*2882Svi117747 	msg_content->sip_content_start = malloc(strlen(content) + 1);
482*2882Svi117747 	if (msg_content->sip_content_start == NULL) {
483*2882Svi117747 		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
484*2882Svi117747 		free(msg_content);
485*2882Svi117747 		return (ENOMEM);
486*2882Svi117747 	}
487*2882Svi117747 	(void) strncpy(msg_content->sip_content_start, content,
488*2882Svi117747 	    strlen(content));
489*2882Svi117747 	msg_content->sip_content_start[strlen(content)] = '\0';
490*2882Svi117747 	msg_content->sip_content_current = msg_content->sip_content_start;
491*2882Svi117747 	msg_content->sip_content_end = msg_content->sip_content_start +
492*2882Svi117747 	    strlen(msg_content->sip_content_start);
493*2882Svi117747 	msg_content->sip_content_allocated = B_TRUE;
494*2882Svi117747 
495*2882Svi117747 	loc = &_sip_msg->sip_msg_content;
496*2882Svi117747 	while (*loc != NULL)
497*2882Svi117747 		loc = &((*loc)->sip_content_next);
498*2882Svi117747 	*loc = msg_content;
499*2882Svi117747 
500*2882Svi117747 	_sip_msg->sip_msg_content_len += len;
501*2882Svi117747 	_sip_msg->sip_msg_len += len;
502*2882Svi117747 	if (_sip_msg->sip_msg_buf != NULL)
503*2882Svi117747 		_sip_msg->sip_msg_modified = B_TRUE;
504*2882Svi117747 	(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
505*2882Svi117747 	return (0);
506*2882Svi117747 }
507*2882Svi117747 
508*2882Svi117747 /*
509*2882Svi117747  * Free the message content
510*2882Svi117747  */
511*2882Svi117747 void
512*2882Svi117747 sip_free_content(_sip_msg_t *sip_msg)
513*2882Svi117747 {
514*2882Svi117747 	sip_content_t *content;
515*2882Svi117747 
516*2882Svi117747 	if (sip_msg == NULL)
517*2882Svi117747 		return;
518*2882Svi117747 	content = sip_msg->sip_msg_content;
519*2882Svi117747 	while (content != NULL) {
520*2882Svi117747 		sip_content_t *content_tmp;
521*2882Svi117747 
522*2882Svi117747 		content_tmp = content;
523*2882Svi117747 		content = content->sip_content_next;
524*2882Svi117747 		if (content_tmp->sip_content_allocated)
525*2882Svi117747 			free(content_tmp->sip_content_start);
526*2882Svi117747 		free(content_tmp);
527*2882Svi117747 	}
528*2882Svi117747 	sip_msg->sip_msg_content = NULL;
529*2882Svi117747 }
530*2882Svi117747 
531*2882Svi117747 
532*2882Svi117747 /*
533*2882Svi117747  * Add a response line to sip_response
534*2882Svi117747  */
535*2882Svi117747 int
536*2882Svi117747 sip_add_response_line(sip_msg_t sip_response, int response, char *response_code)
537*2882Svi117747 {
538*2882Svi117747 	_sip_header_t	*new_header;
539*2882Svi117747 	int		header_size;
540*2882Svi117747 	_sip_msg_t	*_sip_response;
541*2882Svi117747 	int		ret;
542*2882Svi117747 
543*2882Svi117747 	if (sip_response == NULL || response < 0 || response_code == NULL)
544*2882Svi117747 		return (EINVAL);
545*2882Svi117747 	_sip_response = (_sip_msg_t *)sip_response;
546*2882Svi117747 	(void) pthread_mutex_lock(&_sip_response->sip_msg_mutex);
547*2882Svi117747 	if (_sip_response->sip_msg_cannot_be_modified) {
548*2882Svi117747 		(void) pthread_mutex_unlock(&_sip_response->sip_msg_mutex);
549*2882Svi117747 		return (ENOTSUP);
550*2882Svi117747 	}
551*2882Svi117747 	header_size = strlen(SIP_VERSION) + SIP_SPACE_LEN +
552*2882Svi117747 	    SIP_SIZE_OF_STATUS_CODE + SIP_SPACE_LEN + strlen(response_code) +
553*2882Svi117747 	    strlen(SIP_CRLF);
554*2882Svi117747 
555*2882Svi117747 	new_header = sip_new_header(header_size);
556*2882Svi117747 	if (new_header == NULL) {
557*2882Svi117747 		(void) pthread_mutex_unlock(&_sip_response->sip_msg_mutex);
558*2882Svi117747 		return (ENOMEM);
559*2882Svi117747 	}
560*2882Svi117747 	new_header->sip_hdr_sipmsg = _sip_response;
561*2882Svi117747 
562*2882Svi117747 	(void) snprintf(new_header->sip_hdr_start, header_size + 1,
563*2882Svi117747 	    SIP_RESPONSE, SIP_VERSION, response, response_code, SIP_CRLF);
564*2882Svi117747 
565*2882Svi117747 	new_header->sip_hdr_next = _sip_response->sip_msg_start_line;
566*2882Svi117747 	_sip_response->sip_msg_start_line = new_header;
567*2882Svi117747 	_sip_response->sip_msg_len += header_size;
568*2882Svi117747 	ret = sip_parse_first_line(_sip_response->sip_msg_start_line,
569*2882Svi117747 	    &_sip_response->sip_msg_req_res);
570*2882Svi117747 	if (_sip_response->sip_msg_buf != NULL)
571*2882Svi117747 		_sip_response->sip_msg_modified = B_TRUE;
572*2882Svi117747 	(void) pthread_mutex_unlock(&_sip_response->sip_msg_mutex);
573*2882Svi117747 	return (ret);
574*2882Svi117747 }
575*2882Svi117747 
576*2882Svi117747 /*
577*2882Svi117747  * create a response based on the sip_request.
578*2882Svi117747  * Copies Call-ID, CSeq, From, To and Via headers from the request.
579*2882Svi117747  */
580*2882Svi117747 sip_msg_t
581*2882Svi117747 sip_create_response(sip_msg_t sip_request, int response, char *response_code,
582*2882Svi117747     char *totag, char *mycontact)
583*2882Svi117747 {
584*2882Svi117747 	_sip_msg_t	*new_msg;
585*2882Svi117747 	_sip_msg_t	*_sip_request;
586*2882Svi117747 	boolean_t	ttag_present;
587*2882Svi117747 
588*2882Svi117747 	if (sip_request == NULL || response_code == NULL)
589*2882Svi117747 		return (NULL);
590*2882Svi117747 
591*2882Svi117747 	ttag_present =  sip_get_to_tag(sip_request, NULL) != NULL;
592*2882Svi117747 
593*2882Svi117747 	new_msg = (_sip_msg_t *)sip_new_msg();
594*2882Svi117747 	if (new_msg == NULL)
595*2882Svi117747 		return (NULL);
596*2882Svi117747 	_sip_request = (_sip_msg_t *)sip_request;
597*2882Svi117747 
598*2882Svi117747 	(void) pthread_mutex_lock(&_sip_request->sip_msg_mutex);
599*2882Svi117747 
600*2882Svi117747 	/*
601*2882Svi117747 	 * Add response line.
602*2882Svi117747 	 */
603*2882Svi117747 	if (sip_add_response_line(new_msg, response, response_code) != 0)
604*2882Svi117747 		goto error;
605*2882Svi117747 
606*2882Svi117747 	/*
607*2882Svi117747 	 * Copy Via headers
608*2882Svi117747 	 */
609*2882Svi117747 	if (_sip_find_and_copy_all_header(_sip_request, new_msg, SIP_VIA) != 0)
610*2882Svi117747 		goto error;
611*2882Svi117747 
612*2882Svi117747 	/*
613*2882Svi117747 	 * Copy From header.
614*2882Svi117747 	 */
615*2882Svi117747 	if (_sip_find_and_copy_header(_sip_request, new_msg, SIP_FROM,
616*2882Svi117747 	    NULL, B_FALSE)) {
617*2882Svi117747 		goto error;
618*2882Svi117747 	}
619*2882Svi117747 	/*
620*2882Svi117747 	 * Copy To header. If To tag is present, copy it, if not then
621*2882Svi117747 	 * add one if the repsonse is not provisional.
622*2882Svi117747 	 */
623*2882Svi117747 	if (ttag_present || (totag == NULL && response == SIP_TRYING)) {
624*2882Svi117747 		if (_sip_find_and_copy_header(_sip_request, new_msg, SIP_TO,
625*2882Svi117747 		    NULL, B_FALSE)) {
626*2882Svi117747 			goto error;
627*2882Svi117747 		}
628*2882Svi117747 	} else {
629*2882Svi117747 		char		*xtra_param;
630*2882Svi117747 		boolean_t	tag_alloc = B_FALSE;
631*2882Svi117747 		int		taglen;
632*2882Svi117747 
633*2882Svi117747 		if (totag == NULL) {
634*2882Svi117747 			totag = sip_guid();
635*2882Svi117747 			if (totag == NULL)
636*2882Svi117747 				goto error;
637*2882Svi117747 			tag_alloc = B_TRUE;
638*2882Svi117747 		}
639*2882Svi117747 		taglen = strlen(SIP_TAG) + strlen(totag) + 1;
640*2882Svi117747 		xtra_param = (char *)malloc(taglen);
641*2882Svi117747 		if (xtra_param == NULL) {
642*2882Svi117747 			if (tag_alloc)
643*2882Svi117747 				free(totag);
644*2882Svi117747 			goto error;
645*2882Svi117747 		}
646*2882Svi117747 		(void) snprintf(xtra_param, taglen, "%s%s", SIP_TAG, totag);
647*2882Svi117747 		if (tag_alloc)
648*2882Svi117747 			free(totag);
649*2882Svi117747 		if (_sip_find_and_copy_header(_sip_request, new_msg,
650*2882Svi117747 		    SIP_TO, xtra_param, B_FALSE)) {
651*2882Svi117747 			free(xtra_param);
652*2882Svi117747 			goto error;
653*2882Svi117747 		}
654*2882Svi117747 		free(xtra_param);
655*2882Svi117747 	}
656*2882Svi117747 
657*2882Svi117747 	/*
658*2882Svi117747 	 * Copy Call-ID header.
659*2882Svi117747 	 */
660*2882Svi117747 	if (_sip_find_and_copy_header(_sip_request, new_msg, SIP_CALL_ID, NULL,
661*2882Svi117747 	    B_FALSE)) {
662*2882Svi117747 		goto error;
663*2882Svi117747 	}
664*2882Svi117747 	/*
665*2882Svi117747 	 * Copy CSEQ header
666*2882Svi117747 	 */
667*2882Svi117747 	if (_sip_find_and_copy_header(_sip_request, new_msg, SIP_CSEQ, NULL,
668*2882Svi117747 	    B_FALSE)) {
669*2882Svi117747 		goto error;
670*2882Svi117747 	}
671*2882Svi117747 	/*
672*2882Svi117747 	 * Copy RECORD-ROUTE header, if present.
673*2882Svi117747 	 */
674*2882Svi117747 	if (sip_search_for_header(_sip_request, SIP_RECORD_ROUTE, NULL) !=
675*2882Svi117747 	    NULL) {
676*2882Svi117747 		if (_sip_find_and_copy_all_header(_sip_request, new_msg,
677*2882Svi117747 		    SIP_RECORD_ROUTE) != 0) {
678*2882Svi117747 			goto error;
679*2882Svi117747 		}
680*2882Svi117747 	}
681*2882Svi117747 	if (mycontact != NULL) {
682*2882Svi117747 		if (sip_add_contact(new_msg, NULL, mycontact, B_FALSE,
683*2882Svi117747 		    NULL) != 0) {
684*2882Svi117747 			goto error;
685*2882Svi117747 		}
686*2882Svi117747 	}
687*2882Svi117747 	(void) pthread_mutex_unlock(&_sip_request->sip_msg_mutex);
688*2882Svi117747 	return ((sip_msg_t)new_msg);
689*2882Svi117747 error:
690*2882Svi117747 	sip_free_msg((sip_msg_t)new_msg);
691*2882Svi117747 	(void) pthread_mutex_unlock(&_sip_request->sip_msg_mutex);
692*2882Svi117747 	return (NULL);
693*2882Svi117747 }
694*2882Svi117747 
695*2882Svi117747 /*
696*2882Svi117747  * NON OK ACK : MUST contain values for the Call-ID, From, and Request-URI
697*2882Svi117747  * that are equal to the values of those header fields in the orig request
698*2882Svi117747  * passed to the transport. The To header field in the ACK MUST equal the To
699*2882Svi117747  * header field in the response being acknowledged. The ACK MUST contain the
700*2882Svi117747  * top Via header field of the original request.  The CSeq header field in
701*2882Svi117747  * the ACK MUST contain the same value for the sequence number as was
702*2882Svi117747  * present in the original request, but the method parameter MUST be equal
703*2882Svi117747  * to "ACK".
704*2882Svi117747  */
705*2882Svi117747 int
706*2882Svi117747 sip_create_nonOKack(sip_msg_t request, sip_msg_t response, sip_msg_t ack_msg)
707*2882Svi117747 {
708*2882Svi117747 	int		seqno;
709*2882Svi117747 	char		*uri;
710*2882Svi117747 	_sip_msg_t	*_request;
711*2882Svi117747 	_sip_msg_t	*_response;
712*2882Svi117747 	_sip_msg_t	*_ack_msg;
713*2882Svi117747 	int		ret;
714*2882Svi117747 
715*2882Svi117747 	if (request == NULL || response == NULL || ack_msg == NULL ||
716*2882Svi117747 	    request == ack_msg) {
717*2882Svi117747 		return (EINVAL);
718*2882Svi117747 	}
719*2882Svi117747 	_request = (_sip_msg_t *)request;
720*2882Svi117747 	_response = (_sip_msg_t *)response;
721*2882Svi117747 	_ack_msg = (_sip_msg_t *)ack_msg;
722*2882Svi117747 
723*2882Svi117747 	(void) pthread_mutex_lock(&_request->sip_msg_mutex);
724*2882Svi117747 	if (_request->sip_msg_req_res == NULL) {
725*2882Svi117747 		if ((ret = sip_parse_first_line(_request->sip_msg_start_line,
726*2882Svi117747 		    &_request->sip_msg_req_res)) != 0) {
727*2882Svi117747 			(void) pthread_mutex_unlock(&_request->sip_msg_mutex);
728*2882Svi117747 			return (ret);
729*2882Svi117747 		}
730*2882Svi117747 	}
731*2882Svi117747 	if (_request->sip_msg_req_res->U.sip_request.sip_request_uri.
732*2882Svi117747 	    sip_str_ptr == NULL) {
733*2882Svi117747 		(void) pthread_mutex_unlock(&_request->sip_msg_mutex);
734*2882Svi117747 		return (EINVAL);
735*2882Svi117747 	}
736*2882Svi117747 	uri = (char *)malloc(_request->sip_msg_req_res->U.sip_request.
737*2882Svi117747 	    sip_request_uri.sip_str_len + 1);
738*2882Svi117747 	if (uri == NULL) {
739*2882Svi117747 		(void) pthread_mutex_unlock(&_request->sip_msg_mutex);
740*2882Svi117747 		return (EINVAL);
741*2882Svi117747 	}
742*2882Svi117747 	(void) strncpy(uri,
743*2882Svi117747 	    _request->sip_msg_req_res->U.sip_request.sip_request_uri.
744*2882Svi117747 	    sip_str_ptr, _request->sip_msg_req_res->U.sip_request.
745*2882Svi117747 	    sip_request_uri.sip_str_len);
746*2882Svi117747 	uri[_request->sip_msg_req_res->U.sip_request.
747*2882Svi117747 	    sip_request_uri.sip_str_len] = '\0';
748*2882Svi117747 	if ((ret = sip_add_request_line(_ack_msg, ACK, uri)) != 0) {
749*2882Svi117747 		(void) pthread_mutex_unlock(&_request->sip_msg_mutex);
750*2882Svi117747 		return (ret);
751*2882Svi117747 	}
752*2882Svi117747 	free(uri);
753*2882Svi117747 	if ((ret = _sip_find_and_copy_header(_request, _ack_msg, SIP_VIA,
754*2882Svi117747 	    NULL, B_TRUE)) != 0) {
755*2882Svi117747 		(void) pthread_mutex_unlock(&_request->sip_msg_mutex);
756*2882Svi117747 		return (ret);
757*2882Svi117747 	}
758*2882Svi117747 	(void) _sip_find_and_copy_header(_request, _ack_msg,
759*2882Svi117747 	    SIP_MAX_FORWARDS, NULL, B_TRUE);
760*2882Svi117747 
761*2882Svi117747 	(void) pthread_mutex_lock(&_response->sip_msg_mutex);
762*2882Svi117747 	if ((ret = _sip_find_and_copy_header(_response, _ack_msg, SIP_TO,
763*2882Svi117747 	    NULL, B_TRUE)) != 0) {
764*2882Svi117747 		(void) pthread_mutex_unlock(&_response->sip_msg_mutex);
765*2882Svi117747 		return (ret);
766*2882Svi117747 	}
767*2882Svi117747 	(void) pthread_mutex_unlock(&_response->sip_msg_mutex);
768*2882Svi117747 	if ((ret = _sip_find_and_copy_header(_request, _ack_msg, SIP_FROM,
769*2882Svi117747 	    NULL, B_TRUE)) != 0) {
770*2882Svi117747 		(void) pthread_mutex_unlock(&_request->sip_msg_mutex);
771*2882Svi117747 		return (ret);
772*2882Svi117747 	}
773*2882Svi117747 	if ((ret = _sip_find_and_copy_header(_request, _ack_msg, SIP_CALL_ID,
774*2882Svi117747 	    NULL, B_TRUE)) != 0) {
775*2882Svi117747 		(void) pthread_mutex_unlock(&_request->sip_msg_mutex);
776*2882Svi117747 		return (ret);
777*2882Svi117747 	}
778*2882Svi117747 	(void) pthread_mutex_unlock(&_request->sip_msg_mutex);
779*2882Svi117747 	seqno = sip_get_callseq_num(_request, &ret);
780*2882Svi117747 	if (ret != 0)
781*2882Svi117747 		return (ret);
782*2882Svi117747 	if ((ret = sip_add_cseq(_ack_msg, ACK, seqno)) != 0)
783*2882Svi117747 		return (ret);
784*2882Svi117747 	if ((ret = sip_adjust_msgbuf(_ack_msg)) != 0)
785*2882Svi117747 		return (ret);
786*2882Svi117747 	return (0);
787*2882Svi117747 }
788*2882Svi117747 
789*2882Svi117747 /*
790*2882Svi117747  * This is a 2XX ACK, for others ACK is constructed differently,
791*2882Svi117747  * esp. the branch id is retained.
792*2882Svi117747  */
793*2882Svi117747 int
794*2882Svi117747 sip_create_OKack(sip_msg_t response, sip_msg_t ack_msg, char *transport,
795*2882Svi117747     char *sent_by, int sent_by_port, char *via_params)
796*2882Svi117747 {
797*2882Svi117747 	int			seqno;
798*2882Svi117747 	char			*uri;
799*2882Svi117747 	sip_parsed_header_t	*parsed_header;
800*2882Svi117747 	sip_hdr_value_t		*contact_value;
801*2882Svi117747 	_sip_header_t		*header;
802*2882Svi117747 	_sip_msg_t		*_response;
803*2882Svi117747 	_sip_msg_t		*_ack_msg;
804*2882Svi117747 	int			ret;
805*2882Svi117747 
806*2882Svi117747 	if (response == NULL || response == NULL || transport == NULL)
807*2882Svi117747 		return (EINVAL);
808*2882Svi117747 	_response = (_sip_msg_t *)response;
809*2882Svi117747 	_ack_msg = (_sip_msg_t *)ack_msg;
810*2882Svi117747 
811*2882Svi117747 	/*
812*2882Svi117747 	 * Get URI from the response, Contact field
813*2882Svi117747 	 */
814*2882Svi117747 	(void) pthread_mutex_lock(&_response->sip_msg_mutex);
815*2882Svi117747 	if ((header = sip_search_for_header(_response, SIP_CONTACT,
816*2882Svi117747 	    NULL)) == NULL) {
817*2882Svi117747 		(void) pthread_mutex_unlock(&_response->sip_msg_mutex);
818*2882Svi117747 		return (EINVAL);
819*2882Svi117747 	}
820*2882Svi117747 	if ((ret = sip_parse_cftr_header(header, (void *)&parsed_header)) !=
821*2882Svi117747 	    0) {
822*2882Svi117747 		(void) pthread_mutex_unlock(&_response->sip_msg_mutex);
823*2882Svi117747 		return (ret);
824*2882Svi117747 	}
825*2882Svi117747 	contact_value = (sip_hdr_value_t *)parsed_header->value;
826*2882Svi117747 	if (contact_value->cftr_uri.sip_str_ptr == NULL) {
827*2882Svi117747 		(void) pthread_mutex_unlock(&_response->sip_msg_mutex);
828*2882Svi117747 		return (EINVAL);
829*2882Svi117747 	}
830*2882Svi117747 	uri = (char *)malloc(contact_value->cftr_uri.sip_str_len + 1);
831*2882Svi117747 	if (uri == NULL) {
832*2882Svi117747 		(void) pthread_mutex_unlock(&_response->sip_msg_mutex);
833*2882Svi117747 		return (ENOMEM);
834*2882Svi117747 	}
835*2882Svi117747 	(void) strncpy(uri, contact_value->cftr_uri.sip_str_ptr,
836*2882Svi117747 	    contact_value->cftr_uri.sip_str_len);
837*2882Svi117747 	uri[contact_value->cftr_uri.sip_str_len] = '\0';
838*2882Svi117747 	if ((ret = sip_add_request_line(_ack_msg, ACK, uri)) != 0) {
839*2882Svi117747 		(void) pthread_mutex_unlock(&_response->sip_msg_mutex);
840*2882Svi117747 		return (ret);
841*2882Svi117747 	}
842*2882Svi117747 	free(uri);
843*2882Svi117747 	if ((ret = sip_add_via(_ack_msg, transport, sent_by, sent_by_port,
844*2882Svi117747 	    via_params)) != 0) {
845*2882Svi117747 		(void) pthread_mutex_unlock(&_response->sip_msg_mutex);
846*2882Svi117747 		return (ret);
847*2882Svi117747 	}
848*2882Svi117747 
849*2882Svi117747 	if ((ret = _sip_find_and_copy_header(_response, _ack_msg, SIP_TO,
850*2882Svi117747 	    NULL, B_TRUE)) != 0) {
851*2882Svi117747 		(void) pthread_mutex_unlock(&_response->sip_msg_mutex);
852*2882Svi117747 		return (ret);
853*2882Svi117747 	}
854*2882Svi117747 	if ((ret = _sip_find_and_copy_header(_response, _ack_msg, SIP_FROM,
855*2882Svi117747 	    NULL, B_TRUE)) != 0) {
856*2882Svi117747 		(void) pthread_mutex_unlock(&_response->sip_msg_mutex);
857*2882Svi117747 		return (ret);
858*2882Svi117747 	}
859*2882Svi117747 	if ((ret = _sip_find_and_copy_header(_response, _ack_msg, SIP_CALL_ID,
860*2882Svi117747 	    NULL, B_TRUE)) != 0) {
861*2882Svi117747 		(void) pthread_mutex_unlock(&_response->sip_msg_mutex);
862*2882Svi117747 		return (ret);
863*2882Svi117747 	}
864*2882Svi117747 	/*
865*2882Svi117747 	 * Copy Max-Forward if present
866*2882Svi117747 	 */
867*2882Svi117747 	if (sip_search_for_header(_response, SIP_MAX_FORWARDS, NULL) != NULL) {
868*2882Svi117747 		if ((ret = _sip_find_and_copy_header(_response, _ack_msg,
869*2882Svi117747 		    SIP_MAX_FORWARDS, NULL, B_TRUE)) != 0) {
870*2882Svi117747 			(void) pthread_mutex_unlock(&_response->sip_msg_mutex);
871*2882Svi117747 			return (ret);
872*2882Svi117747 		}
873*2882Svi117747 	}
874*2882Svi117747 	(void) pthread_mutex_unlock(&_response->sip_msg_mutex);
875*2882Svi117747 	seqno = sip_get_callseq_num(_response, &ret);
876*2882Svi117747 	if (ret != 0)
877*2882Svi117747 		return (ret);
878*2882Svi117747 	if ((ret = sip_add_cseq(_ack_msg, ACK, seqno)) != 0)
879*2882Svi117747 		return (ret);
880*2882Svi117747 
881*2882Svi117747 	return (0);
882*2882Svi117747 }
883*2882Svi117747 
884*2882Svi117747 /*
885*2882Svi117747  * Request-Line   =  Method SP Request-URI SP SIP-Version CRLF
886*2882Svi117747  */
887*2882Svi117747 int
888*2882Svi117747 sip_add_request_line(sip_msg_t sip_request, sip_method_t method,
889*2882Svi117747     char *request_uri)
890*2882Svi117747 {
891*2882Svi117747 	_sip_header_t	*new_header;
892*2882Svi117747 	int		 header_size;
893*2882Svi117747 	_sip_msg_t	*_sip_request;
894*2882Svi117747 
895*2882Svi117747 	if (method < INVITE || method >= MAX_SIP_METHODS ||
896*2882Svi117747 	    request_uri == NULL || sip_request == NULL) {
897*2882Svi117747 		return (EINVAL);
898*2882Svi117747 	}
899*2882Svi117747 
900*2882Svi117747 	_sip_request = (_sip_msg_t *)sip_request;
901*2882Svi117747 	(void) pthread_mutex_lock(&_sip_request->sip_msg_mutex);
902*2882Svi117747 	if (_sip_request->sip_msg_cannot_be_modified) {
903*2882Svi117747 		(void) pthread_mutex_unlock(&_sip_request->sip_msg_mutex);
904*2882Svi117747 		return (ENOTSUP);
905*2882Svi117747 	}
906*2882Svi117747 
907*2882Svi117747 	header_size = strlen(sip_methods[method].name) + SIP_SPACE_LEN +
908*2882Svi117747 	    strlen(request_uri) + SIP_SPACE_LEN + strlen(SIP_VERSION) +
909*2882Svi117747 	    strlen(SIP_CRLF);
910*2882Svi117747 
911*2882Svi117747 	new_header = sip_new_header(header_size);
912*2882Svi117747 	if (new_header == NULL) {
913*2882Svi117747 		(void) pthread_mutex_unlock(&_sip_request->sip_msg_mutex);
914*2882Svi117747 		return (ENOMEM);
915*2882Svi117747 	}
916*2882Svi117747 	new_header->sip_hdr_sipmsg = _sip_request;
917*2882Svi117747 
918*2882Svi117747 	(void) snprintf(new_header->sip_hdr_start, header_size + 1,
919*2882Svi117747 	    "%s %s %s%s", sip_methods[method].name, request_uri,
920*2882Svi117747 	    SIP_VERSION, SIP_CRLF);
921*2882Svi117747 
922*2882Svi117747 	new_header->sip_hdr_next = _sip_request->sip_msg_start_line;
923*2882Svi117747 	_sip_request->sip_msg_start_line = new_header;
924*2882Svi117747 	_sip_request->sip_msg_len += header_size;
925*2882Svi117747 	(void) sip_parse_first_line(_sip_request->sip_msg_start_line,
926*2882Svi117747 	    &_sip_request->sip_msg_req_res);
927*2882Svi117747 	if (_sip_request->sip_msg_buf != NULL)
928*2882Svi117747 		_sip_request->sip_msg_modified = B_TRUE;
929*2882Svi117747 	(void) pthread_mutex_unlock(&_sip_request->sip_msg_mutex);
930*2882Svi117747 	return (0);
931*2882Svi117747 }
932