140cb5e5dSvi117747 /* 240cb5e5dSvi117747 * CDDL HEADER START 340cb5e5dSvi117747 * 440cb5e5dSvi117747 * The contents of this file are subject to the terms of the 540cb5e5dSvi117747 * Common Development and Distribution License (the "License"). 640cb5e5dSvi117747 * You may not use this file except in compliance with the License. 740cb5e5dSvi117747 * 840cb5e5dSvi117747 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 940cb5e5dSvi117747 * or http://www.opensolaris.org/os/licensing. 1040cb5e5dSvi117747 * See the License for the specific language governing permissions 1140cb5e5dSvi117747 * and limitations under the License. 1240cb5e5dSvi117747 * 1340cb5e5dSvi117747 * When distributing Covered Code, include this CDDL HEADER in each 1440cb5e5dSvi117747 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1540cb5e5dSvi117747 * If applicable, add the following below this CDDL HEADER, with the 1640cb5e5dSvi117747 * fields enclosed by brackets "[]" replaced with your own identifying 1740cb5e5dSvi117747 * information: Portions Copyright [yyyy] [name of copyright owner] 1840cb5e5dSvi117747 * 1940cb5e5dSvi117747 * CDDL HEADER END 2040cb5e5dSvi117747 */ 2140cb5e5dSvi117747 2240cb5e5dSvi117747 /* 23*2c2c4183Svi117747 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 2440cb5e5dSvi117747 * Use is subject to license terms. 2540cb5e5dSvi117747 */ 2640cb5e5dSvi117747 2740cb5e5dSvi117747 #pragma ident "%Z%%M% %I% %E% SMI" 2840cb5e5dSvi117747 29*2c2c4183Svi117747 #include <stdio.h> 30*2c2c4183Svi117747 #include <assert.h> 31*2c2c4183Svi117747 #include <errno.h> 32*2c2c4183Svi117747 #include <pthread.h> 33*2c2c4183Svi117747 #include <stdlib.h> 34*2c2c4183Svi117747 #include <string.h> 35*2c2c4183Svi117747 #include <sip.h> 36*2c2c4183Svi117747 3740cb5e5dSvi117747 #include "sip_msg.h" 3840cb5e5dSvi117747 #include "sip_miscdefs.h" 3940cb5e5dSvi117747 #include "sip_parse_generic.h" 4040cb5e5dSvi117747 4140cb5e5dSvi117747 /* 4240cb5e5dSvi117747 * Response consists of SIP version, response code, response phrase and CRLF. 4340cb5e5dSvi117747 */ 4440cb5e5dSvi117747 #define SIP_RESPONSE "%s %d %s%s" 4540cb5e5dSvi117747 4640cb5e5dSvi117747 void sip_free_content(_sip_msg_t *); 4740cb5e5dSvi117747 4840cb5e5dSvi117747 /* 4940cb5e5dSvi117747 * Allocate a new sip msg struct. 5040cb5e5dSvi117747 */ 5140cb5e5dSvi117747 sip_msg_t 5240cb5e5dSvi117747 sip_new_msg() 5340cb5e5dSvi117747 { 5440cb5e5dSvi117747 _sip_msg_t *sip_msg; 5540cb5e5dSvi117747 5640cb5e5dSvi117747 sip_msg = calloc(1, sizeof (_sip_msg_t)); 5740cb5e5dSvi117747 if (sip_msg != NULL) { 5840cb5e5dSvi117747 sip_msg->sip_msg_ref_cnt = 1; 5940cb5e5dSvi117747 (void) pthread_mutex_init(&sip_msg->sip_msg_mutex, NULL); 6040cb5e5dSvi117747 } 6140cb5e5dSvi117747 return ((sip_msg_t)sip_msg); 6240cb5e5dSvi117747 } 6340cb5e5dSvi117747 6440cb5e5dSvi117747 /* 6540cb5e5dSvi117747 * Free all resources. The lock is taken by SIP_MSG_REFCNT_DECR. The 6640cb5e5dSvi117747 * thread that decrements the last refcount should take care that 6740cb5e5dSvi117747 * the message is not accessible to other threads before doing so. 6840cb5e5dSvi117747 * Else, if the message is still accessible to others, it is 6940cb5e5dSvi117747 * possible that the other thread could be waiting to take the 7040cb5e5dSvi117747 * lock when we proceed to destroy it. 7140cb5e5dSvi117747 */ 7240cb5e5dSvi117747 void 7340cb5e5dSvi117747 sip_destroy_msg(_sip_msg_t *_sip_msg) 7440cb5e5dSvi117747 { 7540cb5e5dSvi117747 #ifdef __solaris__ 7640cb5e5dSvi117747 assert(mutex_held(&_sip_msg->sip_msg_mutex)); 7740cb5e5dSvi117747 #endif 7840cb5e5dSvi117747 (void) sip_delete_start_line_locked(_sip_msg); 7940cb5e5dSvi117747 assert(_sip_msg->sip_msg_ref_cnt == 0); 8040cb5e5dSvi117747 sip_delete_all_headers((sip_msg_t)_sip_msg); 8140cb5e5dSvi117747 sip_free_content(_sip_msg); 8240cb5e5dSvi117747 if (_sip_msg->sip_msg_buf != NULL) 8340cb5e5dSvi117747 free(_sip_msg->sip_msg_buf); 8440cb5e5dSvi117747 8540cb5e5dSvi117747 if (_sip_msg->sip_msg_old_buf != NULL) 8640cb5e5dSvi117747 free(_sip_msg->sip_msg_old_buf); 8740cb5e5dSvi117747 8840cb5e5dSvi117747 while (_sip_msg->sip_msg_req_res != NULL) { 8940cb5e5dSvi117747 sip_message_type_t *sip_msg_type_ptr; 9040cb5e5dSvi117747 9140cb5e5dSvi117747 sip_msg_type_ptr = _sip_msg->sip_msg_req_res->sip_next; 9240cb5e5dSvi117747 if (_sip_msg->sip_msg_req_res->is_request) { 9340cb5e5dSvi117747 sip_request_t *reqline; 9440cb5e5dSvi117747 9540cb5e5dSvi117747 reqline = &_sip_msg->sip_msg_req_res->U.sip_request; 9640cb5e5dSvi117747 if (reqline->sip_parse_uri != NULL) { 9740cb5e5dSvi117747 sip_free_parsed_uri(reqline->sip_parse_uri); 9840cb5e5dSvi117747 reqline->sip_parse_uri = NULL; 9940cb5e5dSvi117747 } 10040cb5e5dSvi117747 } 10140cb5e5dSvi117747 free(_sip_msg->sip_msg_req_res); 10240cb5e5dSvi117747 _sip_msg->sip_msg_req_res = sip_msg_type_ptr; 10340cb5e5dSvi117747 } 10440cb5e5dSvi117747 (void) pthread_mutex_destroy(&_sip_msg->sip_msg_mutex); 10540cb5e5dSvi117747 free(_sip_msg); 10640cb5e5dSvi117747 } 10740cb5e5dSvi117747 10840cb5e5dSvi117747 /* 10940cb5e5dSvi117747 * Free a sip msg struct. 11040cb5e5dSvi117747 */ 11140cb5e5dSvi117747 void 11240cb5e5dSvi117747 sip_free_msg(sip_msg_t sip_msg) 11340cb5e5dSvi117747 { 11440cb5e5dSvi117747 if (sip_msg == NULL) 11540cb5e5dSvi117747 return; 11640cb5e5dSvi117747 11740cb5e5dSvi117747 SIP_MSG_REFCNT_DECR((_sip_msg_t *)sip_msg); 11840cb5e5dSvi117747 } 11940cb5e5dSvi117747 12040cb5e5dSvi117747 /* 12140cb5e5dSvi117747 * Hold a sip msg struct. 12240cb5e5dSvi117747 */ 12340cb5e5dSvi117747 void 12440cb5e5dSvi117747 sip_hold_msg(sip_msg_t sip_msg) 12540cb5e5dSvi117747 { 12640cb5e5dSvi117747 12740cb5e5dSvi117747 if (sip_msg == NULL) 12840cb5e5dSvi117747 return; 12940cb5e5dSvi117747 13040cb5e5dSvi117747 SIP_MSG_REFCNT_INCR((_sip_msg_t *)sip_msg); 13140cb5e5dSvi117747 } 13240cb5e5dSvi117747 13340cb5e5dSvi117747 /* 13440cb5e5dSvi117747 * Clone a message 13540cb5e5dSvi117747 */ 13640cb5e5dSvi117747 sip_msg_t 13740cb5e5dSvi117747 sip_clone_msg(sip_msg_t sip_msg) 13840cb5e5dSvi117747 { 13940cb5e5dSvi117747 _sip_msg_t *new_msg; 14040cb5e5dSvi117747 _sip_msg_t *_sip_msg; 14140cb5e5dSvi117747 sip_content_t *sip_content; 14240cb5e5dSvi117747 sip_content_t *msg_content; 14340cb5e5dSvi117747 sip_content_t *new_content = NULL; 14440cb5e5dSvi117747 int len; 14540cb5e5dSvi117747 14640cb5e5dSvi117747 if (sip_msg == NULL) 14740cb5e5dSvi117747 return (NULL); 14840cb5e5dSvi117747 new_msg = (_sip_msg_t *)sip_new_msg(); 14940cb5e5dSvi117747 if (new_msg == NULL) 15040cb5e5dSvi117747 return (NULL); 15140cb5e5dSvi117747 _sip_msg = (_sip_msg_t *)sip_msg; 15240cb5e5dSvi117747 /* 15340cb5e5dSvi117747 * Get start line 15440cb5e5dSvi117747 */ 15540cb5e5dSvi117747 if (sip_copy_start_line(_sip_msg, new_msg) != 0) { 15640cb5e5dSvi117747 sip_free_msg((sip_msg_t)new_msg); 15740cb5e5dSvi117747 return (NULL); 15840cb5e5dSvi117747 } 15940cb5e5dSvi117747 if (sip_copy_all_headers(_sip_msg, new_msg) != 0) { 16040cb5e5dSvi117747 sip_free_msg((sip_msg_t)new_msg); 16140cb5e5dSvi117747 return (NULL); 16240cb5e5dSvi117747 } 16340cb5e5dSvi117747 (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex); 16440cb5e5dSvi117747 sip_content = _sip_msg->sip_msg_content; 16540cb5e5dSvi117747 while (sip_content != NULL) { 16640cb5e5dSvi117747 msg_content = calloc(1, sizeof (sip_content_t)); 16740cb5e5dSvi117747 if (msg_content == NULL) { 16840cb5e5dSvi117747 sip_free_msg((sip_msg_t)new_msg); 16940cb5e5dSvi117747 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); 17040cb5e5dSvi117747 return (NULL); 17140cb5e5dSvi117747 } 17240cb5e5dSvi117747 len = sip_content->sip_content_end - 17340cb5e5dSvi117747 sip_content->sip_content_start; 17440cb5e5dSvi117747 msg_content->sip_content_start = malloc(len + 1); 17540cb5e5dSvi117747 if (msg_content->sip_content_start == NULL) { 17640cb5e5dSvi117747 sip_free_msg((sip_msg_t)new_msg); 17740cb5e5dSvi117747 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); 17840cb5e5dSvi117747 return (NULL); 17940cb5e5dSvi117747 } 18040cb5e5dSvi117747 (void) strncpy(msg_content->sip_content_start, 18140cb5e5dSvi117747 sip_content->sip_content_start, len); 18240cb5e5dSvi117747 msg_content->sip_content_start[len] = '\0'; 18340cb5e5dSvi117747 msg_content->sip_content_current = 18440cb5e5dSvi117747 msg_content->sip_content_start; 18540cb5e5dSvi117747 msg_content->sip_content_end = msg_content->sip_content_start + 18640cb5e5dSvi117747 len; 18740cb5e5dSvi117747 msg_content->sip_content_allocated = B_TRUE; 18840cb5e5dSvi117747 new_msg->sip_msg_content_len += len; 18940cb5e5dSvi117747 new_msg->sip_msg_len += len; 19040cb5e5dSvi117747 if (new_msg->sip_msg_content == NULL) 19140cb5e5dSvi117747 new_msg->sip_msg_content = msg_content; 19240cb5e5dSvi117747 else 19340cb5e5dSvi117747 new_content->sip_content_next = msg_content; 19440cb5e5dSvi117747 new_content = msg_content; 19540cb5e5dSvi117747 sip_content = sip_content->sip_content_next; 19640cb5e5dSvi117747 } 19740cb5e5dSvi117747 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); 19840cb5e5dSvi117747 /* 19940cb5e5dSvi117747 * Since this is a new message, no threads should be referring 20040cb5e5dSvi117747 * to this, so it is not necessary to take the lock, however, 20140cb5e5dSvi117747 * since sip_msg_to_msgbuf() expects the lock to be held, we'll 20240cb5e5dSvi117747 * take it here. 20340cb5e5dSvi117747 */ 20440cb5e5dSvi117747 (void) pthread_mutex_lock(&new_msg->sip_msg_mutex); 20540cb5e5dSvi117747 new_msg->sip_msg_buf = sip_msg_to_msgbuf((sip_msg_t)new_msg, NULL); 20640cb5e5dSvi117747 if (new_msg->sip_msg_buf == NULL) { 20740cb5e5dSvi117747 (void) pthread_mutex_unlock(&new_msg->sip_msg_mutex); 20840cb5e5dSvi117747 sip_free_msg((sip_msg_t)new_msg); 20940cb5e5dSvi117747 return (NULL); 21040cb5e5dSvi117747 } 21140cb5e5dSvi117747 new_msg->sip_msg_cannot_be_modified = B_TRUE; 21240cb5e5dSvi117747 (void) pthread_mutex_unlock(&new_msg->sip_msg_mutex); 21340cb5e5dSvi117747 21440cb5e5dSvi117747 return ((sip_msg_t)new_msg); 21540cb5e5dSvi117747 } 21640cb5e5dSvi117747 21740cb5e5dSvi117747 /* 21840cb5e5dSvi117747 * Return the SIP message as a string. Caller frees the string 21940cb5e5dSvi117747 */ 22040cb5e5dSvi117747 char * 22140cb5e5dSvi117747 sip_msg_to_str(sip_msg_t sip_msg, int *error) 22240cb5e5dSvi117747 { 22340cb5e5dSvi117747 _sip_msg_t *msg; 22440cb5e5dSvi117747 char *msgstr; 22540cb5e5dSvi117747 22640cb5e5dSvi117747 if (sip_msg == NULL) { 22740cb5e5dSvi117747 if (error != NULL) 22840cb5e5dSvi117747 *error = EINVAL; 22940cb5e5dSvi117747 return (NULL); 23040cb5e5dSvi117747 } 23140cb5e5dSvi117747 msg = (_sip_msg_t *)sip_msg; 23240cb5e5dSvi117747 (void) pthread_mutex_lock(&msg->sip_msg_mutex); 23340cb5e5dSvi117747 msgstr = sip_msg_to_msgbuf(msg, error); 23440cb5e5dSvi117747 (void) pthread_mutex_unlock(&msg->sip_msg_mutex); 23540cb5e5dSvi117747 return (msgstr); 23640cb5e5dSvi117747 } 23740cb5e5dSvi117747 23840cb5e5dSvi117747 /* 23940cb5e5dSvi117747 * Given a message generate a string that includes all the headers and the 24040cb5e5dSvi117747 * content. 24140cb5e5dSvi117747 */ 24240cb5e5dSvi117747 char * 24340cb5e5dSvi117747 sip_msg_to_msgbuf(_sip_msg_t *msg, int *error) 24440cb5e5dSvi117747 { 24540cb5e5dSvi117747 _sip_header_t *header; 24640cb5e5dSvi117747 int len = 0; 24740cb5e5dSvi117747 char *p; 24840cb5e5dSvi117747 char *e; 24940cb5e5dSvi117747 sip_content_t *sip_content; 25040cb5e5dSvi117747 #ifdef _DEBUG 25140cb5e5dSvi117747 int tlen = 0; 25240cb5e5dSvi117747 int clen = 0; 25340cb5e5dSvi117747 #endif 25440cb5e5dSvi117747 25540cb5e5dSvi117747 if (error != NULL) 25640cb5e5dSvi117747 *error = 0; 25740cb5e5dSvi117747 25840cb5e5dSvi117747 if (msg == NULL) { 25940cb5e5dSvi117747 if (error != NULL) 26040cb5e5dSvi117747 *error = EINVAL; 26140cb5e5dSvi117747 return (NULL); 26240cb5e5dSvi117747 } 26340cb5e5dSvi117747 #ifdef __solaris__ 26440cb5e5dSvi117747 assert(mutex_held(&msg->sip_msg_mutex)); 26540cb5e5dSvi117747 #endif 26640cb5e5dSvi117747 26740cb5e5dSvi117747 p = (char *)malloc(msg->sip_msg_len + 1); 26840cb5e5dSvi117747 if (p == NULL) { 26940cb5e5dSvi117747 if (error != 0) 27040cb5e5dSvi117747 *error = ENOMEM; 27140cb5e5dSvi117747 return (NULL); 27240cb5e5dSvi117747 } 27340cb5e5dSvi117747 e = p; 27440cb5e5dSvi117747 27540cb5e5dSvi117747 /* 27640cb5e5dSvi117747 * Get the start line 27740cb5e5dSvi117747 */ 27840cb5e5dSvi117747 if (msg->sip_msg_start_line != NULL) { 27940cb5e5dSvi117747 len = msg->sip_msg_start_line->sip_hdr_end - 28040cb5e5dSvi117747 msg->sip_msg_start_line->sip_hdr_start; 28140cb5e5dSvi117747 (void) strncpy(e, msg->sip_msg_start_line->sip_hdr_start, len); 28240cb5e5dSvi117747 e += len; 28340cb5e5dSvi117747 #ifdef _DEBUG 28440cb5e5dSvi117747 tlen += len; 28540cb5e5dSvi117747 #endif 28640cb5e5dSvi117747 } 28740cb5e5dSvi117747 header = sip_search_for_header(msg, NULL, NULL); 28840cb5e5dSvi117747 while (header != NULL) { 28940cb5e5dSvi117747 if (header->sip_header_state != SIP_HEADER_DELETED) { 29040cb5e5dSvi117747 if (header->sip_header_state == 29140cb5e5dSvi117747 SIP_HEADER_DELETED_VAL) { 29240cb5e5dSvi117747 len = sip_copy_values(e, header); 29340cb5e5dSvi117747 } else { 29440cb5e5dSvi117747 len = header->sip_hdr_end - 29540cb5e5dSvi117747 header->sip_hdr_start; 29640cb5e5dSvi117747 (void) strncpy(e, header->sip_hdr_start, len); 29740cb5e5dSvi117747 } 29840cb5e5dSvi117747 #ifdef _DEBUG 29940cb5e5dSvi117747 tlen += len; 30040cb5e5dSvi117747 assert(tlen <= msg->sip_msg_len); 30140cb5e5dSvi117747 #endif 30240cb5e5dSvi117747 } 30340cb5e5dSvi117747 header = sip_search_for_header(msg, NULL, header); 30440cb5e5dSvi117747 e += len; 30540cb5e5dSvi117747 } 30640cb5e5dSvi117747 sip_content = msg->sip_msg_content; 30740cb5e5dSvi117747 while (sip_content != NULL) { 30840cb5e5dSvi117747 len = sip_content->sip_content_end - 30940cb5e5dSvi117747 sip_content->sip_content_start; 31040cb5e5dSvi117747 #ifdef _DEBUG 31140cb5e5dSvi117747 clen += len; 31240cb5e5dSvi117747 assert(clen <= msg->sip_msg_content_len); 31340cb5e5dSvi117747 tlen += len; 31440cb5e5dSvi117747 assert(tlen <= msg->sip_msg_len); 31540cb5e5dSvi117747 #endif 31640cb5e5dSvi117747 (void) strncpy(e, sip_content->sip_content_start, len); 31740cb5e5dSvi117747 e += len; 31840cb5e5dSvi117747 sip_content = sip_content->sip_content_next; 31940cb5e5dSvi117747 } 32040cb5e5dSvi117747 p[msg->sip_msg_len] = '\0'; 32140cb5e5dSvi117747 return (p); 32240cb5e5dSvi117747 } 32340cb5e5dSvi117747 32440cb5e5dSvi117747 /* 32540cb5e5dSvi117747 * This is called just before sending the message to the transport. It 32640cb5e5dSvi117747 * creates the sip_msg_buf from the SIP headers. 32740cb5e5dSvi117747 */ 32840cb5e5dSvi117747 int 32940cb5e5dSvi117747 sip_adjust_msgbuf(_sip_msg_t *msg) 33040cb5e5dSvi117747 { 33140cb5e5dSvi117747 _sip_header_t *header; 33240cb5e5dSvi117747 int ret; 33340cb5e5dSvi117747 #ifdef _DEBUG 33440cb5e5dSvi117747 int tlen = 0; 33540cb5e5dSvi117747 int clen = 0; 33640cb5e5dSvi117747 #endif 33740cb5e5dSvi117747 33840cb5e5dSvi117747 if (msg == NULL) 33940cb5e5dSvi117747 return (EINVAL); 34040cb5e5dSvi117747 34140cb5e5dSvi117747 (void) pthread_mutex_lock(&msg->sip_msg_mutex); 34240cb5e5dSvi117747 if ((msg->sip_msg_buf != NULL) && (!msg->sip_msg_modified)) { 34340cb5e5dSvi117747 /* 34440cb5e5dSvi117747 * We could just be forwarding the message we 34540cb5e5dSvi117747 * received. 34640cb5e5dSvi117747 */ 34740cb5e5dSvi117747 (void) pthread_mutex_unlock(&msg->sip_msg_mutex); 34840cb5e5dSvi117747 return (0); 34940cb5e5dSvi117747 } 35040cb5e5dSvi117747 35140cb5e5dSvi117747 /* 35240cb5e5dSvi117747 * We are sending a new message or a message that we received 35340cb5e5dSvi117747 * but have modified it. We keep the old 35440cb5e5dSvi117747 * msgbuf till the message is freed as some 35540cb5e5dSvi117747 * headers still point to it. 35640cb5e5dSvi117747 */ 35740cb5e5dSvi117747 35840cb5e5dSvi117747 assert(msg->sip_msg_old_buf == NULL); 35940cb5e5dSvi117747 msg->sip_msg_old_buf = msg->sip_msg_buf; 36040cb5e5dSvi117747 /* 36140cb5e5dSvi117747 * We add the content-length header here, if it has not 36240cb5e5dSvi117747 * already been added. 36340cb5e5dSvi117747 */ 36440cb5e5dSvi117747 header = sip_search_for_header(msg, SIP_CONTENT_LENGTH, NULL); 36540cb5e5dSvi117747 if (header != NULL) { 36640cb5e5dSvi117747 /* 36740cb5e5dSvi117747 * Mark the previous header as deleted. 36840cb5e5dSvi117747 */ 36940cb5e5dSvi117747 header->sip_header_state = SIP_HEADER_DELETED; 37040cb5e5dSvi117747 header->sip_hdr_sipmsg->sip_msg_len -= header->sip_hdr_end - 37140cb5e5dSvi117747 header->sip_hdr_start; 37240cb5e5dSvi117747 } 37340cb5e5dSvi117747 (void) pthread_mutex_unlock(&msg->sip_msg_mutex); 37440cb5e5dSvi117747 ret = sip_add_content_length(msg, msg->sip_msg_content_len); 37540cb5e5dSvi117747 if (ret != 0) { 37640cb5e5dSvi117747 (void) pthread_mutex_unlock(&msg->sip_msg_mutex); 37740cb5e5dSvi117747 return (ret); 37840cb5e5dSvi117747 } 37940cb5e5dSvi117747 (void) pthread_mutex_lock(&msg->sip_msg_mutex); 38040cb5e5dSvi117747 msg->sip_msg_modified = B_FALSE; 38140cb5e5dSvi117747 38240cb5e5dSvi117747 msg->sip_msg_buf = sip_msg_to_msgbuf((sip_msg_t)msg, &ret); 38340cb5e5dSvi117747 if (msg->sip_msg_buf == NULL) { 38440cb5e5dSvi117747 (void) pthread_mutex_unlock(&msg->sip_msg_mutex); 38540cb5e5dSvi117747 return (ret); 38640cb5e5dSvi117747 } 38740cb5e5dSvi117747 /* 38840cb5e5dSvi117747 * Once the message has been sent it can not be modified 38940cb5e5dSvi117747 * any furthur as we keep a pointer to it for retransmission 39040cb5e5dSvi117747 */ 39140cb5e5dSvi117747 msg->sip_msg_cannot_be_modified = B_TRUE; 39240cb5e5dSvi117747 39340cb5e5dSvi117747 (void) pthread_mutex_unlock(&msg->sip_msg_mutex); 39440cb5e5dSvi117747 return (0); 39540cb5e5dSvi117747 } 39640cb5e5dSvi117747 39740cb5e5dSvi117747 /* 39840cb5e5dSvi117747 * Copy header values into ptr 39940cb5e5dSvi117747 */ 40040cb5e5dSvi117747 int 40140cb5e5dSvi117747 sip_copy_values(char *ptr, _sip_header_t *header) 40240cb5e5dSvi117747 { 40340cb5e5dSvi117747 sip_header_value_t value; 40440cb5e5dSvi117747 int tlen = 0; 40540cb5e5dSvi117747 int len = 0; 40640cb5e5dSvi117747 boolean_t first = B_TRUE; 40740cb5e5dSvi117747 char *p = ptr; 40840cb5e5dSvi117747 char *s; 40940cb5e5dSvi117747 boolean_t crlf_present = B_FALSE; 41040cb5e5dSvi117747 41140cb5e5dSvi117747 if (sip_parse_goto_values(header) != 0) 41240cb5e5dSvi117747 return (0); 41340cb5e5dSvi117747 41440cb5e5dSvi117747 len = header->sip_hdr_current - header->sip_hdr_start; 41540cb5e5dSvi117747 (void) strncpy(p, header->sip_hdr_start, len); 41640cb5e5dSvi117747 tlen += len; 41740cb5e5dSvi117747 p += len; 41840cb5e5dSvi117747 value = header->sip_hdr_parsed->value; 41940cb5e5dSvi117747 while (value != NULL) { 42040cb5e5dSvi117747 if (value->value_state != SIP_VALUE_DELETED) { 42140cb5e5dSvi117747 crlf_present = B_FALSE; 42240cb5e5dSvi117747 len = value->value_end - value->value_start; 42340cb5e5dSvi117747 if (first) { 42440cb5e5dSvi117747 (void) strncpy(p, value->value_start, len); 42540cb5e5dSvi117747 first = B_FALSE; 42640cb5e5dSvi117747 } else { 42740cb5e5dSvi117747 s = value->value_start; 42840cb5e5dSvi117747 while (*s != SIP_COMMA) 42940cb5e5dSvi117747 s--; 43040cb5e5dSvi117747 len += value->value_start - s; 43140cb5e5dSvi117747 (void) strncpy(p, s, len); 43240cb5e5dSvi117747 } 43340cb5e5dSvi117747 tlen += len; 43440cb5e5dSvi117747 p += len; 43540cb5e5dSvi117747 s = value->value_end; 43640cb5e5dSvi117747 while (s != value->value_start) { 43740cb5e5dSvi117747 if (*s == '\r' && strncmp(s, SIP_CRLF, 43840cb5e5dSvi117747 strlen(SIP_CRLF)) == 0) { 43940cb5e5dSvi117747 crlf_present = B_TRUE; 44040cb5e5dSvi117747 break; 44140cb5e5dSvi117747 } 44240cb5e5dSvi117747 s--; 44340cb5e5dSvi117747 } 44440cb5e5dSvi117747 } else { 44540cb5e5dSvi117747 if (value->next == NULL && !first && !crlf_present) { 44640cb5e5dSvi117747 s = value->value_end; 44740cb5e5dSvi117747 while (*s != '\r') 44840cb5e5dSvi117747 s--; 44940cb5e5dSvi117747 len = value->value_end - s; 45040cb5e5dSvi117747 (void) strncpy(p, s, len); 45140cb5e5dSvi117747 tlen += len; 45240cb5e5dSvi117747 p += len; 45340cb5e5dSvi117747 } 45440cb5e5dSvi117747 } 45540cb5e5dSvi117747 value = value->next; 45640cb5e5dSvi117747 } 45740cb5e5dSvi117747 return (tlen); 45840cb5e5dSvi117747 } 45940cb5e5dSvi117747 46040cb5e5dSvi117747 46140cb5e5dSvi117747 /* 46240cb5e5dSvi117747 * Add content (message body) to sip_msg 46340cb5e5dSvi117747 */ 46440cb5e5dSvi117747 int 46540cb5e5dSvi117747 sip_add_content(sip_msg_t sip_msg, char *content) 46640cb5e5dSvi117747 { 46740cb5e5dSvi117747 size_t len; 46840cb5e5dSvi117747 sip_content_t **loc; 46940cb5e5dSvi117747 sip_content_t *msg_content; 47040cb5e5dSvi117747 _sip_msg_t *_sip_msg; 47140cb5e5dSvi117747 47240cb5e5dSvi117747 if (sip_msg == NULL || content == NULL || strlen(content) == 0) 47340cb5e5dSvi117747 return (EINVAL); 47440cb5e5dSvi117747 len = strlen(content); 47540cb5e5dSvi117747 _sip_msg = (_sip_msg_t *)sip_msg; 47640cb5e5dSvi117747 (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex); 47740cb5e5dSvi117747 47840cb5e5dSvi117747 if (_sip_msg->sip_msg_cannot_be_modified) { 47940cb5e5dSvi117747 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); 48040cb5e5dSvi117747 return (ENOTSUP); 48140cb5e5dSvi117747 } 48240cb5e5dSvi117747 48340cb5e5dSvi117747 msg_content = calloc(1, sizeof (sip_content_t)); 48440cb5e5dSvi117747 if (msg_content == NULL) { 48540cb5e5dSvi117747 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); 48640cb5e5dSvi117747 return (ENOMEM); 48740cb5e5dSvi117747 } 48840cb5e5dSvi117747 msg_content->sip_content_start = malloc(strlen(content) + 1); 48940cb5e5dSvi117747 if (msg_content->sip_content_start == NULL) { 49040cb5e5dSvi117747 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); 49140cb5e5dSvi117747 free(msg_content); 49240cb5e5dSvi117747 return (ENOMEM); 49340cb5e5dSvi117747 } 49440cb5e5dSvi117747 (void) strncpy(msg_content->sip_content_start, content, 49540cb5e5dSvi117747 strlen(content)); 49640cb5e5dSvi117747 msg_content->sip_content_start[strlen(content)] = '\0'; 49740cb5e5dSvi117747 msg_content->sip_content_current = msg_content->sip_content_start; 49840cb5e5dSvi117747 msg_content->sip_content_end = msg_content->sip_content_start + 49940cb5e5dSvi117747 strlen(msg_content->sip_content_start); 50040cb5e5dSvi117747 msg_content->sip_content_allocated = B_TRUE; 50140cb5e5dSvi117747 50240cb5e5dSvi117747 loc = &_sip_msg->sip_msg_content; 50340cb5e5dSvi117747 while (*loc != NULL) 50440cb5e5dSvi117747 loc = &((*loc)->sip_content_next); 50540cb5e5dSvi117747 *loc = msg_content; 50640cb5e5dSvi117747 50740cb5e5dSvi117747 _sip_msg->sip_msg_content_len += len; 50840cb5e5dSvi117747 _sip_msg->sip_msg_len += len; 50940cb5e5dSvi117747 if (_sip_msg->sip_msg_buf != NULL) 51040cb5e5dSvi117747 _sip_msg->sip_msg_modified = B_TRUE; 51140cb5e5dSvi117747 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); 51240cb5e5dSvi117747 return (0); 51340cb5e5dSvi117747 } 51440cb5e5dSvi117747 51540cb5e5dSvi117747 /* 51640cb5e5dSvi117747 * Free the message content 51740cb5e5dSvi117747 */ 51840cb5e5dSvi117747 void 51940cb5e5dSvi117747 sip_free_content(_sip_msg_t *sip_msg) 52040cb5e5dSvi117747 { 52140cb5e5dSvi117747 sip_content_t *content; 52240cb5e5dSvi117747 52340cb5e5dSvi117747 if (sip_msg == NULL) 52440cb5e5dSvi117747 return; 52540cb5e5dSvi117747 content = sip_msg->sip_msg_content; 52640cb5e5dSvi117747 while (content != NULL) { 52740cb5e5dSvi117747 sip_content_t *content_tmp; 52840cb5e5dSvi117747 52940cb5e5dSvi117747 content_tmp = content; 53040cb5e5dSvi117747 content = content->sip_content_next; 53140cb5e5dSvi117747 if (content_tmp->sip_content_allocated) 53240cb5e5dSvi117747 free(content_tmp->sip_content_start); 53340cb5e5dSvi117747 free(content_tmp); 53440cb5e5dSvi117747 } 53540cb5e5dSvi117747 sip_msg->sip_msg_content = NULL; 53640cb5e5dSvi117747 } 53740cb5e5dSvi117747 53840cb5e5dSvi117747 53940cb5e5dSvi117747 /* 54040cb5e5dSvi117747 * Add a response line to sip_response 54140cb5e5dSvi117747 */ 54240cb5e5dSvi117747 int 54340cb5e5dSvi117747 sip_add_response_line(sip_msg_t sip_response, int response, char *response_code) 54440cb5e5dSvi117747 { 54540cb5e5dSvi117747 _sip_header_t *new_header; 54640cb5e5dSvi117747 int header_size; 54740cb5e5dSvi117747 _sip_msg_t *_sip_response; 54840cb5e5dSvi117747 int ret; 54940cb5e5dSvi117747 55040cb5e5dSvi117747 if (sip_response == NULL || response < 0 || response_code == NULL) 55140cb5e5dSvi117747 return (EINVAL); 55240cb5e5dSvi117747 _sip_response = (_sip_msg_t *)sip_response; 55340cb5e5dSvi117747 (void) pthread_mutex_lock(&_sip_response->sip_msg_mutex); 55440cb5e5dSvi117747 if (_sip_response->sip_msg_cannot_be_modified) { 55540cb5e5dSvi117747 (void) pthread_mutex_unlock(&_sip_response->sip_msg_mutex); 55640cb5e5dSvi117747 return (ENOTSUP); 55740cb5e5dSvi117747 } 55840cb5e5dSvi117747 header_size = strlen(SIP_VERSION) + SIP_SPACE_LEN + 55940cb5e5dSvi117747 SIP_SIZE_OF_STATUS_CODE + SIP_SPACE_LEN + strlen(response_code) + 56040cb5e5dSvi117747 strlen(SIP_CRLF); 56140cb5e5dSvi117747 56240cb5e5dSvi117747 new_header = sip_new_header(header_size); 56340cb5e5dSvi117747 if (new_header == NULL) { 56440cb5e5dSvi117747 (void) pthread_mutex_unlock(&_sip_response->sip_msg_mutex); 56540cb5e5dSvi117747 return (ENOMEM); 56640cb5e5dSvi117747 } 56740cb5e5dSvi117747 new_header->sip_hdr_sipmsg = _sip_response; 56840cb5e5dSvi117747 56940cb5e5dSvi117747 (void) snprintf(new_header->sip_hdr_start, header_size + 1, 57040cb5e5dSvi117747 SIP_RESPONSE, SIP_VERSION, response, response_code, SIP_CRLF); 57140cb5e5dSvi117747 57240cb5e5dSvi117747 new_header->sip_hdr_next = _sip_response->sip_msg_start_line; 57340cb5e5dSvi117747 _sip_response->sip_msg_start_line = new_header; 57440cb5e5dSvi117747 _sip_response->sip_msg_len += header_size; 57540cb5e5dSvi117747 ret = sip_parse_first_line(_sip_response->sip_msg_start_line, 57640cb5e5dSvi117747 &_sip_response->sip_msg_req_res); 57740cb5e5dSvi117747 if (_sip_response->sip_msg_buf != NULL) 57840cb5e5dSvi117747 _sip_response->sip_msg_modified = B_TRUE; 57940cb5e5dSvi117747 (void) pthread_mutex_unlock(&_sip_response->sip_msg_mutex); 58040cb5e5dSvi117747 return (ret); 58140cb5e5dSvi117747 } 58240cb5e5dSvi117747 58340cb5e5dSvi117747 /* 58440cb5e5dSvi117747 * create a response based on the sip_request. 58540cb5e5dSvi117747 * Copies Call-ID, CSeq, From, To and Via headers from the request. 58640cb5e5dSvi117747 */ 58740cb5e5dSvi117747 sip_msg_t 58840cb5e5dSvi117747 sip_create_response(sip_msg_t sip_request, int response, char *response_code, 58940cb5e5dSvi117747 char *totag, char *mycontact) 59040cb5e5dSvi117747 { 59140cb5e5dSvi117747 _sip_msg_t *new_msg; 59240cb5e5dSvi117747 _sip_msg_t *_sip_request; 59340cb5e5dSvi117747 boolean_t ttag_present; 59440cb5e5dSvi117747 59540cb5e5dSvi117747 if (sip_request == NULL || response_code == NULL) 59640cb5e5dSvi117747 return (NULL); 59740cb5e5dSvi117747 59840cb5e5dSvi117747 ttag_present = sip_get_to_tag(sip_request, NULL) != NULL; 59940cb5e5dSvi117747 60040cb5e5dSvi117747 new_msg = (_sip_msg_t *)sip_new_msg(); 60140cb5e5dSvi117747 if (new_msg == NULL) 60240cb5e5dSvi117747 return (NULL); 60340cb5e5dSvi117747 _sip_request = (_sip_msg_t *)sip_request; 60440cb5e5dSvi117747 60540cb5e5dSvi117747 (void) pthread_mutex_lock(&_sip_request->sip_msg_mutex); 60640cb5e5dSvi117747 60740cb5e5dSvi117747 /* 60840cb5e5dSvi117747 * Add response line. 60940cb5e5dSvi117747 */ 61040cb5e5dSvi117747 if (sip_add_response_line(new_msg, response, response_code) != 0) 61140cb5e5dSvi117747 goto error; 61240cb5e5dSvi117747 61340cb5e5dSvi117747 /* 61440cb5e5dSvi117747 * Copy Via headers 61540cb5e5dSvi117747 */ 61640cb5e5dSvi117747 if (_sip_find_and_copy_all_header(_sip_request, new_msg, SIP_VIA) != 0) 61740cb5e5dSvi117747 goto error; 61840cb5e5dSvi117747 61940cb5e5dSvi117747 /* 62040cb5e5dSvi117747 * Copy From header. 62140cb5e5dSvi117747 */ 62240cb5e5dSvi117747 if (_sip_find_and_copy_header(_sip_request, new_msg, SIP_FROM, 62340cb5e5dSvi117747 NULL, B_FALSE)) { 62440cb5e5dSvi117747 goto error; 62540cb5e5dSvi117747 } 62640cb5e5dSvi117747 /* 62740cb5e5dSvi117747 * Copy To header. If To tag is present, copy it, if not then 62840cb5e5dSvi117747 * add one if the repsonse is not provisional. 62940cb5e5dSvi117747 */ 63040cb5e5dSvi117747 if (ttag_present || (totag == NULL && response == SIP_TRYING)) { 63140cb5e5dSvi117747 if (_sip_find_and_copy_header(_sip_request, new_msg, SIP_TO, 63240cb5e5dSvi117747 NULL, B_FALSE)) { 63340cb5e5dSvi117747 goto error; 63440cb5e5dSvi117747 } 63540cb5e5dSvi117747 } else { 63640cb5e5dSvi117747 char *xtra_param; 63740cb5e5dSvi117747 boolean_t tag_alloc = B_FALSE; 63840cb5e5dSvi117747 int taglen; 63940cb5e5dSvi117747 64040cb5e5dSvi117747 if (totag == NULL) { 64140cb5e5dSvi117747 totag = sip_guid(); 64240cb5e5dSvi117747 if (totag == NULL) 64340cb5e5dSvi117747 goto error; 64440cb5e5dSvi117747 tag_alloc = B_TRUE; 64540cb5e5dSvi117747 } 64640cb5e5dSvi117747 taglen = strlen(SIP_TAG) + strlen(totag) + 1; 64740cb5e5dSvi117747 xtra_param = (char *)malloc(taglen); 64840cb5e5dSvi117747 if (xtra_param == NULL) { 64940cb5e5dSvi117747 if (tag_alloc) 65040cb5e5dSvi117747 free(totag); 65140cb5e5dSvi117747 goto error; 65240cb5e5dSvi117747 } 65340cb5e5dSvi117747 (void) snprintf(xtra_param, taglen, "%s%s", SIP_TAG, totag); 65440cb5e5dSvi117747 if (tag_alloc) 65540cb5e5dSvi117747 free(totag); 65640cb5e5dSvi117747 if (_sip_find_and_copy_header(_sip_request, new_msg, 65740cb5e5dSvi117747 SIP_TO, xtra_param, B_FALSE)) { 65840cb5e5dSvi117747 free(xtra_param); 65940cb5e5dSvi117747 goto error; 66040cb5e5dSvi117747 } 66140cb5e5dSvi117747 free(xtra_param); 66240cb5e5dSvi117747 } 66340cb5e5dSvi117747 66440cb5e5dSvi117747 /* 66540cb5e5dSvi117747 * Copy Call-ID header. 66640cb5e5dSvi117747 */ 66740cb5e5dSvi117747 if (_sip_find_and_copy_header(_sip_request, new_msg, SIP_CALL_ID, NULL, 66840cb5e5dSvi117747 B_FALSE)) { 66940cb5e5dSvi117747 goto error; 67040cb5e5dSvi117747 } 67140cb5e5dSvi117747 /* 67240cb5e5dSvi117747 * Copy CSEQ header 67340cb5e5dSvi117747 */ 67440cb5e5dSvi117747 if (_sip_find_and_copy_header(_sip_request, new_msg, SIP_CSEQ, NULL, 67540cb5e5dSvi117747 B_FALSE)) { 67640cb5e5dSvi117747 goto error; 67740cb5e5dSvi117747 } 67840cb5e5dSvi117747 /* 67940cb5e5dSvi117747 * Copy RECORD-ROUTE header, if present. 68040cb5e5dSvi117747 */ 68140cb5e5dSvi117747 if (sip_search_for_header(_sip_request, SIP_RECORD_ROUTE, NULL) != 68240cb5e5dSvi117747 NULL) { 68340cb5e5dSvi117747 if (_sip_find_and_copy_all_header(_sip_request, new_msg, 68440cb5e5dSvi117747 SIP_RECORD_ROUTE) != 0) { 68540cb5e5dSvi117747 goto error; 68640cb5e5dSvi117747 } 68740cb5e5dSvi117747 } 68840cb5e5dSvi117747 if (mycontact != NULL) { 68940cb5e5dSvi117747 if (sip_add_contact(new_msg, NULL, mycontact, B_FALSE, 69040cb5e5dSvi117747 NULL) != 0) { 69140cb5e5dSvi117747 goto error; 69240cb5e5dSvi117747 } 69340cb5e5dSvi117747 } 69440cb5e5dSvi117747 (void) pthread_mutex_unlock(&_sip_request->sip_msg_mutex); 69540cb5e5dSvi117747 return ((sip_msg_t)new_msg); 69640cb5e5dSvi117747 error: 69740cb5e5dSvi117747 sip_free_msg((sip_msg_t)new_msg); 69840cb5e5dSvi117747 (void) pthread_mutex_unlock(&_sip_request->sip_msg_mutex); 69940cb5e5dSvi117747 return (NULL); 70040cb5e5dSvi117747 } 70140cb5e5dSvi117747 70240cb5e5dSvi117747 /* 70340cb5e5dSvi117747 * NON OK ACK : MUST contain values for the Call-ID, From, and Request-URI 70440cb5e5dSvi117747 * that are equal to the values of those header fields in the orig request 70540cb5e5dSvi117747 * passed to the transport. The To header field in the ACK MUST equal the To 70640cb5e5dSvi117747 * header field in the response being acknowledged. The ACK MUST contain the 70740cb5e5dSvi117747 * top Via header field of the original request. The CSeq header field in 70840cb5e5dSvi117747 * the ACK MUST contain the same value for the sequence number as was 70940cb5e5dSvi117747 * present in the original request, but the method parameter MUST be equal 71040cb5e5dSvi117747 * to "ACK". 71140cb5e5dSvi117747 */ 71240cb5e5dSvi117747 int 71340cb5e5dSvi117747 sip_create_nonOKack(sip_msg_t request, sip_msg_t response, sip_msg_t ack_msg) 71440cb5e5dSvi117747 { 71540cb5e5dSvi117747 int seqno; 71640cb5e5dSvi117747 char *uri; 71740cb5e5dSvi117747 _sip_msg_t *_request; 71840cb5e5dSvi117747 _sip_msg_t *_response; 71940cb5e5dSvi117747 _sip_msg_t *_ack_msg; 72040cb5e5dSvi117747 int ret; 72140cb5e5dSvi117747 72240cb5e5dSvi117747 if (request == NULL || response == NULL || ack_msg == NULL || 72340cb5e5dSvi117747 request == ack_msg) { 72440cb5e5dSvi117747 return (EINVAL); 72540cb5e5dSvi117747 } 72640cb5e5dSvi117747 _request = (_sip_msg_t *)request; 72740cb5e5dSvi117747 _response = (_sip_msg_t *)response; 72840cb5e5dSvi117747 _ack_msg = (_sip_msg_t *)ack_msg; 72940cb5e5dSvi117747 73040cb5e5dSvi117747 (void) pthread_mutex_lock(&_request->sip_msg_mutex); 73140cb5e5dSvi117747 if (_request->sip_msg_req_res == NULL) { 73240cb5e5dSvi117747 if ((ret = sip_parse_first_line(_request->sip_msg_start_line, 73340cb5e5dSvi117747 &_request->sip_msg_req_res)) != 0) { 73440cb5e5dSvi117747 (void) pthread_mutex_unlock(&_request->sip_msg_mutex); 73540cb5e5dSvi117747 return (ret); 73640cb5e5dSvi117747 } 73740cb5e5dSvi117747 } 73840cb5e5dSvi117747 if (_request->sip_msg_req_res->U.sip_request.sip_request_uri. 73940cb5e5dSvi117747 sip_str_ptr == NULL) { 74040cb5e5dSvi117747 (void) pthread_mutex_unlock(&_request->sip_msg_mutex); 74140cb5e5dSvi117747 return (EINVAL); 74240cb5e5dSvi117747 } 74340cb5e5dSvi117747 uri = (char *)malloc(_request->sip_msg_req_res->U.sip_request. 74440cb5e5dSvi117747 sip_request_uri.sip_str_len + 1); 74540cb5e5dSvi117747 if (uri == NULL) { 74640cb5e5dSvi117747 (void) pthread_mutex_unlock(&_request->sip_msg_mutex); 74740cb5e5dSvi117747 return (EINVAL); 74840cb5e5dSvi117747 } 74940cb5e5dSvi117747 (void) strncpy(uri, 75040cb5e5dSvi117747 _request->sip_msg_req_res->U.sip_request.sip_request_uri. 75140cb5e5dSvi117747 sip_str_ptr, _request->sip_msg_req_res->U.sip_request. 75240cb5e5dSvi117747 sip_request_uri.sip_str_len); 75340cb5e5dSvi117747 uri[_request->sip_msg_req_res->U.sip_request. 75440cb5e5dSvi117747 sip_request_uri.sip_str_len] = '\0'; 75540cb5e5dSvi117747 if ((ret = sip_add_request_line(_ack_msg, ACK, uri)) != 0) { 75640cb5e5dSvi117747 (void) pthread_mutex_unlock(&_request->sip_msg_mutex); 75740cb5e5dSvi117747 return (ret); 75840cb5e5dSvi117747 } 75940cb5e5dSvi117747 free(uri); 76040cb5e5dSvi117747 if ((ret = _sip_find_and_copy_header(_request, _ack_msg, SIP_VIA, 76140cb5e5dSvi117747 NULL, B_TRUE)) != 0) { 76240cb5e5dSvi117747 (void) pthread_mutex_unlock(&_request->sip_msg_mutex); 76340cb5e5dSvi117747 return (ret); 76440cb5e5dSvi117747 } 76540cb5e5dSvi117747 (void) _sip_find_and_copy_header(_request, _ack_msg, 76640cb5e5dSvi117747 SIP_MAX_FORWARDS, NULL, B_TRUE); 76740cb5e5dSvi117747 76840cb5e5dSvi117747 (void) pthread_mutex_lock(&_response->sip_msg_mutex); 76940cb5e5dSvi117747 if ((ret = _sip_find_and_copy_header(_response, _ack_msg, SIP_TO, 77040cb5e5dSvi117747 NULL, B_TRUE)) != 0) { 77140cb5e5dSvi117747 (void) pthread_mutex_unlock(&_response->sip_msg_mutex); 77240cb5e5dSvi117747 return (ret); 77340cb5e5dSvi117747 } 77440cb5e5dSvi117747 (void) pthread_mutex_unlock(&_response->sip_msg_mutex); 77540cb5e5dSvi117747 if ((ret = _sip_find_and_copy_header(_request, _ack_msg, SIP_FROM, 77640cb5e5dSvi117747 NULL, B_TRUE)) != 0) { 77740cb5e5dSvi117747 (void) pthread_mutex_unlock(&_request->sip_msg_mutex); 77840cb5e5dSvi117747 return (ret); 77940cb5e5dSvi117747 } 78040cb5e5dSvi117747 if ((ret = _sip_find_and_copy_header(_request, _ack_msg, SIP_CALL_ID, 78140cb5e5dSvi117747 NULL, B_TRUE)) != 0) { 78240cb5e5dSvi117747 (void) pthread_mutex_unlock(&_request->sip_msg_mutex); 78340cb5e5dSvi117747 return (ret); 78440cb5e5dSvi117747 } 78540cb5e5dSvi117747 (void) pthread_mutex_unlock(&_request->sip_msg_mutex); 78640cb5e5dSvi117747 seqno = sip_get_callseq_num(_request, &ret); 78740cb5e5dSvi117747 if (ret != 0) 78840cb5e5dSvi117747 return (ret); 78940cb5e5dSvi117747 if ((ret = sip_add_cseq(_ack_msg, ACK, seqno)) != 0) 79040cb5e5dSvi117747 return (ret); 79140cb5e5dSvi117747 if ((ret = sip_adjust_msgbuf(_ack_msg)) != 0) 79240cb5e5dSvi117747 return (ret); 79340cb5e5dSvi117747 return (0); 79440cb5e5dSvi117747 } 79540cb5e5dSvi117747 79640cb5e5dSvi117747 /* 79740cb5e5dSvi117747 * This is a 2XX ACK, for others ACK is constructed differently, 79840cb5e5dSvi117747 * esp. the branch id is retained. 79940cb5e5dSvi117747 */ 80040cb5e5dSvi117747 int 80140cb5e5dSvi117747 sip_create_OKack(sip_msg_t response, sip_msg_t ack_msg, char *transport, 80240cb5e5dSvi117747 char *sent_by, int sent_by_port, char *via_params) 80340cb5e5dSvi117747 { 80440cb5e5dSvi117747 int seqno; 80540cb5e5dSvi117747 char *uri; 80640cb5e5dSvi117747 sip_parsed_header_t *parsed_header; 80740cb5e5dSvi117747 sip_hdr_value_t *contact_value; 80840cb5e5dSvi117747 _sip_header_t *header; 80940cb5e5dSvi117747 _sip_msg_t *_response; 81040cb5e5dSvi117747 _sip_msg_t *_ack_msg; 81140cb5e5dSvi117747 int ret; 81240cb5e5dSvi117747 81340cb5e5dSvi117747 if (response == NULL || response == NULL || transport == NULL) 81440cb5e5dSvi117747 return (EINVAL); 81540cb5e5dSvi117747 _response = (_sip_msg_t *)response; 81640cb5e5dSvi117747 _ack_msg = (_sip_msg_t *)ack_msg; 81740cb5e5dSvi117747 81840cb5e5dSvi117747 /* 81940cb5e5dSvi117747 * Get URI from the response, Contact field 82040cb5e5dSvi117747 */ 82140cb5e5dSvi117747 (void) pthread_mutex_lock(&_response->sip_msg_mutex); 82240cb5e5dSvi117747 if ((header = sip_search_for_header(_response, SIP_CONTACT, 82340cb5e5dSvi117747 NULL)) == NULL) { 82440cb5e5dSvi117747 (void) pthread_mutex_unlock(&_response->sip_msg_mutex); 82540cb5e5dSvi117747 return (EINVAL); 82640cb5e5dSvi117747 } 82740cb5e5dSvi117747 if ((ret = sip_parse_cftr_header(header, (void *)&parsed_header)) != 82840cb5e5dSvi117747 0) { 82940cb5e5dSvi117747 (void) pthread_mutex_unlock(&_response->sip_msg_mutex); 83040cb5e5dSvi117747 return (ret); 83140cb5e5dSvi117747 } 83240cb5e5dSvi117747 contact_value = (sip_hdr_value_t *)parsed_header->value; 83340cb5e5dSvi117747 if (contact_value->cftr_uri.sip_str_ptr == NULL) { 83440cb5e5dSvi117747 (void) pthread_mutex_unlock(&_response->sip_msg_mutex); 83540cb5e5dSvi117747 return (EINVAL); 83640cb5e5dSvi117747 } 83740cb5e5dSvi117747 uri = (char *)malloc(contact_value->cftr_uri.sip_str_len + 1); 83840cb5e5dSvi117747 if (uri == NULL) { 83940cb5e5dSvi117747 (void) pthread_mutex_unlock(&_response->sip_msg_mutex); 84040cb5e5dSvi117747 return (ENOMEM); 84140cb5e5dSvi117747 } 84240cb5e5dSvi117747 (void) strncpy(uri, contact_value->cftr_uri.sip_str_ptr, 84340cb5e5dSvi117747 contact_value->cftr_uri.sip_str_len); 84440cb5e5dSvi117747 uri[contact_value->cftr_uri.sip_str_len] = '\0'; 84540cb5e5dSvi117747 if ((ret = sip_add_request_line(_ack_msg, ACK, uri)) != 0) { 84640cb5e5dSvi117747 (void) pthread_mutex_unlock(&_response->sip_msg_mutex); 84740cb5e5dSvi117747 return (ret); 84840cb5e5dSvi117747 } 84940cb5e5dSvi117747 free(uri); 85040cb5e5dSvi117747 if ((ret = sip_add_via(_ack_msg, transport, sent_by, sent_by_port, 85140cb5e5dSvi117747 via_params)) != 0) { 85240cb5e5dSvi117747 (void) pthread_mutex_unlock(&_response->sip_msg_mutex); 85340cb5e5dSvi117747 return (ret); 85440cb5e5dSvi117747 } 85540cb5e5dSvi117747 85640cb5e5dSvi117747 if ((ret = _sip_find_and_copy_header(_response, _ack_msg, SIP_TO, 85740cb5e5dSvi117747 NULL, B_TRUE)) != 0) { 85840cb5e5dSvi117747 (void) pthread_mutex_unlock(&_response->sip_msg_mutex); 85940cb5e5dSvi117747 return (ret); 86040cb5e5dSvi117747 } 86140cb5e5dSvi117747 if ((ret = _sip_find_and_copy_header(_response, _ack_msg, SIP_FROM, 86240cb5e5dSvi117747 NULL, B_TRUE)) != 0) { 86340cb5e5dSvi117747 (void) pthread_mutex_unlock(&_response->sip_msg_mutex); 86440cb5e5dSvi117747 return (ret); 86540cb5e5dSvi117747 } 86640cb5e5dSvi117747 if ((ret = _sip_find_and_copy_header(_response, _ack_msg, SIP_CALL_ID, 86740cb5e5dSvi117747 NULL, B_TRUE)) != 0) { 86840cb5e5dSvi117747 (void) pthread_mutex_unlock(&_response->sip_msg_mutex); 86940cb5e5dSvi117747 return (ret); 87040cb5e5dSvi117747 } 87140cb5e5dSvi117747 /* 87240cb5e5dSvi117747 * Copy Max-Forward if present 87340cb5e5dSvi117747 */ 87440cb5e5dSvi117747 if (sip_search_for_header(_response, SIP_MAX_FORWARDS, NULL) != NULL) { 87540cb5e5dSvi117747 if ((ret = _sip_find_and_copy_header(_response, _ack_msg, 87640cb5e5dSvi117747 SIP_MAX_FORWARDS, NULL, B_TRUE)) != 0) { 87740cb5e5dSvi117747 (void) pthread_mutex_unlock(&_response->sip_msg_mutex); 87840cb5e5dSvi117747 return (ret); 87940cb5e5dSvi117747 } 88040cb5e5dSvi117747 } 88140cb5e5dSvi117747 (void) pthread_mutex_unlock(&_response->sip_msg_mutex); 88240cb5e5dSvi117747 seqno = sip_get_callseq_num(_response, &ret); 88340cb5e5dSvi117747 if (ret != 0) 88440cb5e5dSvi117747 return (ret); 88540cb5e5dSvi117747 if ((ret = sip_add_cseq(_ack_msg, ACK, seqno)) != 0) 88640cb5e5dSvi117747 return (ret); 88740cb5e5dSvi117747 88840cb5e5dSvi117747 return (0); 88940cb5e5dSvi117747 } 89040cb5e5dSvi117747 89140cb5e5dSvi117747 /* 89240cb5e5dSvi117747 * Request-Line = Method SP Request-URI SP SIP-Version CRLF 89340cb5e5dSvi117747 */ 89440cb5e5dSvi117747 int 89540cb5e5dSvi117747 sip_add_request_line(sip_msg_t sip_request, sip_method_t method, 89640cb5e5dSvi117747 char *request_uri) 89740cb5e5dSvi117747 { 89840cb5e5dSvi117747 _sip_header_t *new_header; 89940cb5e5dSvi117747 int header_size; 90040cb5e5dSvi117747 _sip_msg_t *_sip_request; 90140cb5e5dSvi117747 90240cb5e5dSvi117747 if (method < INVITE || method >= MAX_SIP_METHODS || 90340cb5e5dSvi117747 request_uri == NULL || sip_request == NULL) { 90440cb5e5dSvi117747 return (EINVAL); 90540cb5e5dSvi117747 } 90640cb5e5dSvi117747 90740cb5e5dSvi117747 _sip_request = (_sip_msg_t *)sip_request; 90840cb5e5dSvi117747 (void) pthread_mutex_lock(&_sip_request->sip_msg_mutex); 90940cb5e5dSvi117747 if (_sip_request->sip_msg_cannot_be_modified) { 91040cb5e5dSvi117747 (void) pthread_mutex_unlock(&_sip_request->sip_msg_mutex); 91140cb5e5dSvi117747 return (ENOTSUP); 91240cb5e5dSvi117747 } 91340cb5e5dSvi117747 91440cb5e5dSvi117747 header_size = strlen(sip_methods[method].name) + SIP_SPACE_LEN + 91540cb5e5dSvi117747 strlen(request_uri) + SIP_SPACE_LEN + strlen(SIP_VERSION) + 91640cb5e5dSvi117747 strlen(SIP_CRLF); 91740cb5e5dSvi117747 91840cb5e5dSvi117747 new_header = sip_new_header(header_size); 91940cb5e5dSvi117747 if (new_header == NULL) { 92040cb5e5dSvi117747 (void) pthread_mutex_unlock(&_sip_request->sip_msg_mutex); 92140cb5e5dSvi117747 return (ENOMEM); 92240cb5e5dSvi117747 } 92340cb5e5dSvi117747 new_header->sip_hdr_sipmsg = _sip_request; 92440cb5e5dSvi117747 92540cb5e5dSvi117747 (void) snprintf(new_header->sip_hdr_start, header_size + 1, 92640cb5e5dSvi117747 "%s %s %s%s", sip_methods[method].name, request_uri, 92740cb5e5dSvi117747 SIP_VERSION, SIP_CRLF); 92840cb5e5dSvi117747 92940cb5e5dSvi117747 new_header->sip_hdr_next = _sip_request->sip_msg_start_line; 93040cb5e5dSvi117747 _sip_request->sip_msg_start_line = new_header; 93140cb5e5dSvi117747 _sip_request->sip_msg_len += header_size; 93240cb5e5dSvi117747 (void) sip_parse_first_line(_sip_request->sip_msg_start_line, 93340cb5e5dSvi117747 &_sip_request->sip_msg_req_res); 93440cb5e5dSvi117747 if (_sip_request->sip_msg_buf != NULL) 93540cb5e5dSvi117747 _sip_request->sip_msg_modified = B_TRUE; 93640cb5e5dSvi117747 (void) pthread_mutex_unlock(&_sip_request->sip_msg_mutex); 93740cb5e5dSvi117747 return (0); 93840cb5e5dSvi117747 } 939