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