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 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 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 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 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 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 * 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 * 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 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 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 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 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 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 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 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 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 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