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