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