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