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 <stdlib.h> 30 #include <assert.h> 31 #include <errno.h> 32 #include <pthread.h> 33 #include <sip.h> 34 35 #include "sip_msg.h" 36 #include "sip_miscdefs.h" 37 #include "sip_parse_uri.h" 38 #include "sip_dialog.h" 39 40 /* 41 * Create a request using the state maintained in the dialog. 42 */ 43 sip_msg_t 44 sip_create_dialog_req(sip_method_t method, sip_dialog_t dialog, 45 char *transport, char *sent_by, int sent_by_port, char *via_param, 46 uint32_t maxforward, int cseq) 47 { 48 _sip_dialog_t *_dialog; 49 sip_msg_t sip_msg; 50 char *uri; 51 int oldseq = 0; 52 53 if (!sip_manage_dialog || dialog == NULL || transport == NULL || 54 sent_by == NULL) { 55 return (NULL); 56 } 57 if ((sip_msg = sip_new_msg()) == NULL) 58 return (NULL); 59 _dialog = (_sip_dialog_t *)dialog; 60 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex); 61 /* 62 * Depending on the route set, if any, the request URI could either 63 * be the contact URI or the 1st URI from the route set. 64 */ 65 uri = (char *)sip_dialog_req_uri(_dialog); 66 if (uri == NULL) 67 goto err_ret; 68 if (sip_add_request_line(sip_msg, method, uri) != 0) { 69 free(uri); 70 goto err_ret; 71 } 72 free(uri); 73 if (sip_copy_header(sip_msg, _dialog->sip_dlg_local_uri_tag, NULL) != 0) 74 goto err_ret; 75 if (sip_copy_header(sip_msg, _dialog->sip_dlg_remote_uri_tag, NULL) != 76 0) { 77 goto err_ret; 78 } 79 if (sip_add_via(sip_msg, transport, sent_by, sent_by_port, via_param) != 80 0) { 81 goto err_ret; 82 } 83 if (sip_add_maxforward(sip_msg, maxforward) != 0) 84 goto err_ret; 85 if (sip_copy_header(sip_msg, _dialog->sip_dlg_call_id, NULL) != 0) 86 goto err_ret; 87 if (cseq < 0) { 88 if (_dialog->sip_dlg_local_cseq == 0) 89 _dialog->sip_dlg_local_cseq = 1; 90 oldseq = _dialog->sip_dlg_local_cseq; 91 cseq = ++_dialog->sip_dlg_local_cseq; 92 } 93 if (sip_add_cseq(sip_msg, method, cseq) != 0) { 94 _dialog->sip_dlg_local_cseq = oldseq; 95 goto err_ret; 96 } 97 /* 98 * The route set, even if empty, overrides any pre-existing route set. 99 * If the route set is empty, the UAC MUST NOT add a Route header 100 * field to the request. 101 */ 102 (void) sip_delete_header_by_name(sip_msg, SIP_ROUTE); 103 104 if (_dialog->sip_dlg_route_set != NULL) { 105 if (sip_copy_header(sip_msg, _dialog->sip_dlg_route_set, 106 NULL) != 0) { 107 _dialog->sip_dlg_local_cseq = oldseq; 108 goto err_ret; 109 } 110 } 111 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); 112 return (sip_msg); 113 err_ret: 114 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); 115 sip_free_msg(sip_msg); 116 return (NULL); 117 } 118 119 /* 120 * Get the Dialog method 121 */ 122 int 123 sip_get_dialog_method(sip_dialog_t dialog, int *error) 124 { 125 _sip_dialog_t *_dialog; 126 127 if (error != NULL) 128 *error = 0; 129 if (!sip_manage_dialog) { 130 if (error != NULL) 131 *error = EINVAL; 132 return (0); 133 } 134 if (dialog == NULL) { 135 if (error != NULL) 136 *error = EINVAL; 137 return (0); 138 } 139 _dialog = (_sip_dialog_t *)dialog; 140 return (_dialog->sip_dlg_method); 141 } 142 143 /* 144 * Get the Dialog state 145 */ 146 int 147 sip_get_dialog_state(sip_dialog_t dialog, int *error) 148 { 149 _sip_dialog_t *_dialog; 150 151 if (error != NULL) 152 *error = 0; 153 if (!sip_manage_dialog) { 154 if (error != NULL) 155 *error = EINVAL; 156 return (0); 157 } 158 if (dialog == NULL) { 159 if (error != NULL) 160 *error = EINVAL; 161 return (0); 162 } 163 _dialog = (_sip_dialog_t *)dialog; 164 return (_dialog->sip_dlg_state); 165 } 166 167 /* 168 * Return the dialog callid 169 */ 170 const sip_str_t * 171 sip_get_dialog_callid(sip_dialog_t dialog, int *error) 172 { 173 _sip_dialog_t *_dialog; 174 const struct sip_value *val; 175 const sip_str_t *callid = NULL; 176 177 if (error != NULL) 178 *error = 0; 179 if (!sip_manage_dialog || dialog == NULL) { 180 if (error != NULL) 181 *error = EINVAL; 182 return (NULL); 183 } 184 _dialog = (_sip_dialog_t *)dialog; 185 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex); 186 if (dialog->sip_dlg_call_id != NULL) { 187 val = sip_get_header_value(_dialog->sip_dlg_call_id, error); 188 if (val == NULL) { 189 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); 190 return (NULL); 191 } 192 callid = &((sip_hdr_value_t *)val)->str_val; 193 } 194 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); 195 return (callid); 196 } 197 198 /* 199 * Return the dialog localtag. 200 */ 201 const sip_str_t * 202 sip_get_dialog_local_tag(sip_dialog_t dialog, int *error) 203 { 204 _sip_dialog_t *_dialog; 205 const sip_str_t *ltag = NULL; 206 const struct sip_value *val; 207 208 if (error != NULL) 209 *error = 0; 210 if (!sip_manage_dialog || dialog == NULL) { 211 if (error != NULL) 212 *error = EINVAL; 213 return (NULL); 214 } 215 _dialog = (_sip_dialog_t *)dialog; 216 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex); 217 if (dialog->sip_dlg_local_uri_tag != NULL) { 218 val = sip_get_header_value(_dialog->sip_dlg_local_uri_tag, 219 error); 220 if (val == NULL) { 221 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); 222 return (NULL); 223 } 224 ltag = sip_get_param_value((sip_header_value_t)val, "tag", 225 error); 226 } 227 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); 228 return (ltag); 229 } 230 231 /* 232 * Return the dialog remotetag 233 */ 234 const sip_str_t * 235 sip_get_dialog_remote_tag(sip_dialog_t dialog, int *error) 236 { 237 _sip_dialog_t *_dialog; 238 const sip_str_t *ttag = NULL; 239 const struct sip_value *val; 240 241 if (error != NULL) 242 *error = 0; 243 if (!sip_manage_dialog || dialog == NULL) { 244 if (error != NULL) 245 *error = EINVAL; 246 return (NULL); 247 } 248 _dialog = (_sip_dialog_t *)dialog; 249 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex); 250 if (dialog->sip_dlg_remote_uri_tag != NULL) { 251 val = sip_get_header_value(_dialog->sip_dlg_remote_uri_tag, 252 error); 253 if (val == NULL) { 254 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); 255 return (NULL); 256 } 257 ttag = sip_get_param_value((sip_header_value_t)val, "tag", 258 error); 259 } 260 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); 261 262 return (ttag); 263 } 264 265 /* 266 * Return the dialog localuri. 267 */ 268 const struct sip_uri * 269 sip_get_dialog_local_uri(sip_dialog_t dialog, int *error) 270 { 271 _sip_dialog_t *_dialog; 272 const _sip_uri_t *luri = NULL; 273 const struct sip_value *val; 274 275 if (error != NULL) 276 *error = 0; 277 if (!sip_manage_dialog || dialog == NULL) { 278 if (error != NULL) 279 *error = EINVAL; 280 return (NULL); 281 } 282 _dialog = (_sip_dialog_t *)dialog; 283 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex); 284 if (dialog->sip_dlg_local_uri_tag != NULL) { 285 val = sip_get_header_value(_dialog->sip_dlg_local_uri_tag, 286 error); 287 if (val == NULL) { 288 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); 289 return (NULL); 290 } 291 luri = val->sip_value_parse_uri; 292 } 293 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); 294 295 return ((sip_uri_t)luri); 296 } 297 298 /* 299 * Return the dialog remoteuri. 300 */ 301 const struct sip_uri * 302 sip_get_dialog_remote_uri(sip_dialog_t dialog, int *error) 303 { 304 _sip_dialog_t *_dialog; 305 const _sip_uri_t *ruri = NULL; 306 const struct sip_value *val; 307 308 if (error != NULL) 309 *error = 0; 310 if (!sip_manage_dialog || dialog == NULL) { 311 if (error != NULL) 312 *error = EINVAL; 313 return (NULL); 314 } 315 _dialog = (_sip_dialog_t *)dialog; 316 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex); 317 if (dialog->sip_dlg_remote_uri_tag != NULL) { 318 val = sip_get_header_value(dialog->sip_dlg_remote_uri_tag, 319 error); 320 if (val == NULL) { 321 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); 322 return (NULL); 323 } 324 ruri = val->sip_value_parse_uri; 325 } 326 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); 327 return ((sip_uri_t)ruri); 328 } 329 330 /* 331 * Return the dialog remotetarg. 332 */ 333 const struct sip_uri * 334 sip_get_dialog_remote_target_uri(sip_dialog_t dialog, int *error) 335 { 336 _sip_dialog_t *_dialog; 337 const struct sip_uri *rtarg = NULL; 338 const struct sip_value *val; 339 340 if (error != NULL) 341 *error = 0; 342 if (!sip_manage_dialog || dialog == NULL) { 343 if (error != NULL) 344 *error = EINVAL; 345 return (NULL); 346 } 347 _dialog = (_sip_dialog_t *)dialog; 348 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex); 349 if (dialog->sip_dlg_remote_target != NULL) { 350 val = sip_get_header_value(_dialog->sip_dlg_remote_target, 351 error); 352 if (val == NULL) { 353 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); 354 return (NULL); 355 } 356 rtarg = val->sip_value_parse_uri; 357 } 358 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); 359 360 return ((sip_uri_t)rtarg); 361 } 362 363 /* 364 * Return the dialog route set 365 */ 366 const sip_str_t * 367 sip_get_dialog_route_set(sip_dialog_t dialog, int *error) 368 { 369 _sip_dialog_t *_dialog; 370 371 if (error != NULL) 372 *error = 0; 373 if (!sip_manage_dialog || dialog == NULL) { 374 if (error != NULL) 375 *error = EINVAL; 376 return (NULL); 377 } 378 _dialog = (_sip_dialog_t *)dialog; 379 if (_dialog->sip_dlg_rset.sip_str_len > 0) 380 return (&_dialog->sip_dlg_rset); 381 return (NULL); 382 } 383 384 /* 385 * Return the dialog secure 386 */ 387 boolean_t 388 sip_is_dialog_secure(sip_dialog_t dialog, int *error) 389 { 390 _sip_dialog_t *_dialog; 391 boolean_t issecure; 392 393 if (error != NULL) 394 *error = 0; 395 if (!sip_manage_dialog || dialog == NULL) { 396 if (error != NULL) 397 *error = EINVAL; 398 return (B_FALSE); 399 } 400 _dialog = (_sip_dialog_t *)dialog; 401 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex); 402 issecure = _dialog->sip_dlg_secure; 403 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); 404 return (issecure); 405 } 406 407 /* 408 * Return the dialog local cseq 409 */ 410 uint32_t 411 sip_get_dialog_local_cseq(sip_dialog_t dialog, int *error) 412 { 413 _sip_dialog_t *_dialog; 414 uint32_t cseq; 415 416 if (error != NULL) 417 *error = 0; 418 if (!sip_manage_dialog || dialog == NULL) { 419 if (error != NULL) 420 *error = EINVAL; 421 return (0); 422 } 423 _dialog = (_sip_dialog_t *)dialog; 424 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex); 425 cseq = _dialog->sip_dlg_local_cseq; 426 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); 427 return (cseq); 428 } 429 430 /* 431 * Return the dialog remote cseq 432 */ 433 uint32_t 434 sip_get_dialog_remote_cseq(sip_dialog_t dialog, int *error) 435 { 436 _sip_dialog_t *_dialog; 437 uint32_t cseq; 438 439 if (error != NULL) 440 *error = 0; 441 if (!sip_manage_dialog || dialog == NULL) { 442 if (error != NULL) 443 *error = EINVAL; 444 return (0); 445 } 446 _dialog = (_sip_dialog_t *)dialog; 447 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex); 448 cseq = _dialog->sip_dlg_remote_cseq; 449 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); 450 return (cseq); 451 } 452 453 /* 454 * Return the dialog type 455 */ 456 int 457 sip_get_dialog_type(sip_dialog_t dialog, int *error) 458 { 459 _sip_dialog_t *_dialog; 460 int type; 461 462 if (error != NULL) 463 *error = 0; 464 if (!sip_manage_dialog || dialog == NULL) { 465 if (error != NULL) 466 *error = EINVAL; 467 return (-1); 468 } 469 _dialog = (_sip_dialog_t *)dialog; 470 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex); 471 type = _dialog->sip_dlg_type; 472 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); 473 return (type); 474 } 475 476 477 /* 478 * Partial dialog ? 479 */ 480 boolean_t 481 sip_incomplete_dialog(sip_dialog_t dialog) 482 { 483 _sip_dialog_t *_dialog; 484 boolean_t isnew; 485 486 if (!sip_manage_dialog || dialog == NULL) 487 return (B_FALSE); 488 _dialog = (_sip_dialog_t *)dialog; 489 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex); 490 isnew = _dialog->sip_dlg_state == SIP_DLG_NEW; 491 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); 492 return (isnew); 493 } 494 495 /* 496 * Hold dialog 497 */ 498 void 499 sip_hold_dialog(sip_dialog_t dialog) 500 { 501 _sip_dialog_t *_dialog; 502 503 if (!sip_manage_dialog || dialog == NULL) 504 return; 505 _dialog = (_sip_dialog_t *)dialog; 506 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex); 507 SIP_DLG_REFCNT_INCR(_dialog); 508 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); 509 } 510 511 /* 512 * Release dialog 513 */ 514 void 515 sip_release_dialog(sip_dialog_t dialog) 516 { 517 _sip_dialog_t *_dialog; 518 519 if (!sip_manage_dialog || dialog == NULL) 520 return; 521 _dialog = (_sip_dialog_t *)dialog; 522 SIP_DLG_REFCNT_DECR(_dialog); 523 } 524 525 /* 526 * Delete a dialog 527 */ 528 void 529 sip_delete_dialog(sip_dialog_t dialog) 530 { 531 if (!sip_manage_dialog || dialog == NULL) 532 return; 533 sip_dialog_terminate(dialog, NULL); 534 } 535