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
46 void sip_free_content(_sip_msg_t *);
47
48 /*
49 * Allocate a new sip msg struct.
50 */
51 sip_msg_t
sip_new_msg()52 sip_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 */
72 void
sip_destroy_msg(_sip_msg_t * _sip_msg)73 sip_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 */
111 void
sip_free_msg(sip_msg_t sip_msg)112 sip_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 */
123 void
sip_hold_msg(sip_msg_t sip_msg)124 sip_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 */
136 sip_msg_t
sip_clone_msg(sip_msg_t sip_msg)137 sip_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 */
220 char *
sip_msg_to_str(sip_msg_t sip_msg,int * error)221 sip_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 */
242 char *
sip_msg_to_msgbuf(_sip_msg_t * msg,int * error)243 sip_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 */
328 int
sip_adjust_msgbuf(_sip_msg_t * msg)329 sip_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 */
400 int
sip_copy_values(char * ptr,_sip_header_t * header)401 sip_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 */
464 int
sip_add_content(sip_msg_t sip_msg,char * content)465 sip_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 */
518 void
sip_free_content(_sip_msg_t * sip_msg)519 sip_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 */
542 int
sip_add_response_line(sip_msg_t sip_response,int response,char * response_code)543 sip_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 */
587 sip_msg_t
sip_create_response(sip_msg_t sip_request,int response,char * response_code,char * totag,char * mycontact)588 sip_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);
696 error:
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 */
712 int
sip_create_nonOKack(sip_msg_t request,sip_msg_t response,sip_msg_t ack_msg)713 sip_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 */
800 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)801 sip_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 */
894 int
sip_add_request_line(sip_msg_t sip_request,sip_method_t method,char * request_uri)895 sip_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