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