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