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 2008 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
sip_create_dialog_req(sip_method_t method,sip_dialog_t dialog,char * transport,char * sent_by,int sent_by_port,char * via_param,uint32_t maxforward,int cseq)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_copy_header(sip_msg, _dialog->sip_dlg_local_contact, NULL) != 0)
80 goto err_ret;
81 if (sip_add_via(sip_msg, transport, sent_by, sent_by_port, via_param) !=
82 0) {
83 goto err_ret;
84 }
85 if (sip_add_maxforward(sip_msg, maxforward) != 0)
86 goto err_ret;
87 if (sip_copy_header(sip_msg, _dialog->sip_dlg_call_id, NULL) != 0)
88 goto err_ret;
89 if (cseq < 0) {
90 if (_dialog->sip_dlg_local_cseq == 0)
91 _dialog->sip_dlg_local_cseq = 1;
92 oldseq = _dialog->sip_dlg_local_cseq;
93 cseq = ++_dialog->sip_dlg_local_cseq;
94 }
95 if (sip_add_cseq(sip_msg, method, cseq) != 0) {
96 _dialog->sip_dlg_local_cseq = oldseq;
97 goto err_ret;
98 }
99 /*
100 * The route set, even if empty, overrides any pre-existing route set.
101 * If the route set is empty, the UAC MUST NOT add a Route header
102 * field to the request.
103 */
104 (void) sip_delete_header_by_name(sip_msg, SIP_ROUTE);
105
106 if (_dialog->sip_dlg_route_set != NULL) {
107 if (sip_copy_header(sip_msg, _dialog->sip_dlg_route_set,
108 NULL) != 0) {
109 _dialog->sip_dlg_local_cseq = oldseq;
110 goto err_ret;
111 }
112 }
113 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
114 return (sip_msg);
115 err_ret:
116 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
117 sip_free_msg(sip_msg);
118 return (NULL);
119 }
120
121 /*
122 * Create a request using the state maintained in the dialog. The request will
123 * not have Contact header.
124 */
125 sip_msg_t
sip_create_dialog_req_nocontact(sip_method_t method,sip_dialog_t dialog,char * transport,char * sent_by,int sent_by_port,char * via_param,uint32_t maxforward,int cseq)126 sip_create_dialog_req_nocontact(sip_method_t method, sip_dialog_t dialog,
127 char *transport, char *sent_by, int sent_by_port, char *via_param,
128 uint32_t maxforward, int cseq)
129 {
130 sip_msg_t sip_msg;
131
132 sip_msg = sip_create_dialog_req(method, dialog, transport, sent_by,
133 sent_by_port, via_param, maxforward, cseq);
134 if (sip_msg != NULL) {
135 if (sip_delete_header_by_name(sip_msg, SIP_CONTACT) != 0) {
136 sip_free_msg(sip_msg);
137 return (NULL);
138 }
139 }
140
141 return (sip_msg);
142 }
143
144 /*
145 * Get the Dialog method
146 */
147 int
sip_get_dialog_method(sip_dialog_t dialog,int * error)148 sip_get_dialog_method(sip_dialog_t dialog, int *error)
149 {
150 _sip_dialog_t *_dialog;
151
152 if (error != NULL)
153 *error = 0;
154 if (!sip_manage_dialog) {
155 if (error != NULL)
156 *error = EINVAL;
157 return (0);
158 }
159 if (dialog == NULL) {
160 if (error != NULL)
161 *error = EINVAL;
162 return (0);
163 }
164 _dialog = (_sip_dialog_t *)dialog;
165 return (_dialog->sip_dlg_method);
166 }
167
168 /*
169 * Get the Dialog state
170 */
171 int
sip_get_dialog_state(sip_dialog_t dialog,int * error)172 sip_get_dialog_state(sip_dialog_t dialog, int *error)
173 {
174 _sip_dialog_t *_dialog;
175
176 if (error != NULL)
177 *error = 0;
178 if (!sip_manage_dialog) {
179 if (error != NULL)
180 *error = EINVAL;
181 return (0);
182 }
183 if (dialog == NULL) {
184 if (error != NULL)
185 *error = EINVAL;
186 return (0);
187 }
188 _dialog = (_sip_dialog_t *)dialog;
189 return (_dialog->sip_dlg_state);
190 }
191
192 /*
193 * Return the dialog callid
194 */
195 const sip_str_t *
sip_get_dialog_callid(sip_dialog_t dialog,int * error)196 sip_get_dialog_callid(sip_dialog_t dialog, int *error)
197 {
198 _sip_dialog_t *_dialog;
199 const struct sip_value *val;
200 const sip_str_t *callid = NULL;
201
202 if (error != NULL)
203 *error = 0;
204 if (!sip_manage_dialog || dialog == NULL) {
205 if (error != NULL)
206 *error = EINVAL;
207 return (NULL);
208 }
209 _dialog = (_sip_dialog_t *)dialog;
210 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
211 if (dialog->sip_dlg_call_id != NULL) {
212 val = sip_get_header_value(_dialog->sip_dlg_call_id, error);
213 if (val == NULL) {
214 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
215 return (NULL);
216 }
217 callid = &((sip_hdr_value_t *)val)->str_val;
218 }
219 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
220 return (callid);
221 }
222
223 /*
224 * Return the dialog localtag.
225 */
226 const sip_str_t *
sip_get_dialog_local_tag(sip_dialog_t dialog,int * error)227 sip_get_dialog_local_tag(sip_dialog_t dialog, int *error)
228 {
229 _sip_dialog_t *_dialog;
230 const sip_str_t *ltag = NULL;
231 const struct sip_value *val;
232
233 if (error != NULL)
234 *error = 0;
235 if (!sip_manage_dialog || dialog == NULL) {
236 if (error != NULL)
237 *error = EINVAL;
238 return (NULL);
239 }
240 _dialog = (_sip_dialog_t *)dialog;
241 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
242 if (dialog->sip_dlg_local_uri_tag != NULL) {
243 val = sip_get_header_value(_dialog->sip_dlg_local_uri_tag,
244 error);
245 if (val == NULL) {
246 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
247 return (NULL);
248 }
249 ltag = sip_get_param_value((sip_header_value_t)val, "tag",
250 error);
251 }
252 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
253 return (ltag);
254 }
255
256 /*
257 * Return the dialog remotetag
258 */
259 const sip_str_t *
sip_get_dialog_remote_tag(sip_dialog_t dialog,int * error)260 sip_get_dialog_remote_tag(sip_dialog_t dialog, int *error)
261 {
262 _sip_dialog_t *_dialog;
263 const sip_str_t *ttag = NULL;
264 const struct sip_value *val;
265
266 if (error != NULL)
267 *error = 0;
268 if (!sip_manage_dialog || dialog == NULL) {
269 if (error != NULL)
270 *error = EINVAL;
271 return (NULL);
272 }
273 _dialog = (_sip_dialog_t *)dialog;
274 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
275 if (dialog->sip_dlg_remote_uri_tag != NULL) {
276 val = sip_get_header_value(_dialog->sip_dlg_remote_uri_tag,
277 error);
278 if (val == NULL) {
279 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
280 return (NULL);
281 }
282 ttag = sip_get_param_value((sip_header_value_t)val, "tag",
283 error);
284 }
285 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
286
287 return (ttag);
288 }
289
290 /*
291 * Return the dialog localuri.
292 */
293 const struct sip_uri *
sip_get_dialog_local_uri(sip_dialog_t dialog,int * error)294 sip_get_dialog_local_uri(sip_dialog_t dialog, int *error)
295 {
296 _sip_dialog_t *_dialog;
297 const _sip_uri_t *luri = NULL;
298 const struct sip_value *val;
299
300 if (error != NULL)
301 *error = 0;
302 if (!sip_manage_dialog || dialog == NULL) {
303 if (error != NULL)
304 *error = EINVAL;
305 return (NULL);
306 }
307 _dialog = (_sip_dialog_t *)dialog;
308 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
309 if (dialog->sip_dlg_local_uri_tag != NULL) {
310 val = sip_get_header_value(_dialog->sip_dlg_local_uri_tag,
311 error);
312 if (val == NULL) {
313 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
314 return (NULL);
315 }
316 luri = val->sip_value_parse_uri;
317 }
318 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
319
320 return ((sip_uri_t)luri);
321 }
322
323 /*
324 * Return the dialog remoteuri.
325 */
326 const struct sip_uri *
sip_get_dialog_remote_uri(sip_dialog_t dialog,int * error)327 sip_get_dialog_remote_uri(sip_dialog_t dialog, int *error)
328 {
329 _sip_dialog_t *_dialog;
330 const _sip_uri_t *ruri = NULL;
331 const struct sip_value *val;
332
333 if (error != NULL)
334 *error = 0;
335 if (!sip_manage_dialog || dialog == NULL) {
336 if (error != NULL)
337 *error = EINVAL;
338 return (NULL);
339 }
340 _dialog = (_sip_dialog_t *)dialog;
341 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
342 if (dialog->sip_dlg_remote_uri_tag != NULL) {
343 val = sip_get_header_value(dialog->sip_dlg_remote_uri_tag,
344 error);
345 if (val == NULL) {
346 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
347 return (NULL);
348 }
349 ruri = val->sip_value_parse_uri;
350 }
351 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
352 return ((sip_uri_t)ruri);
353 }
354
355 /*
356 * Return the dialog remotetarg.
357 */
358 const struct sip_uri *
sip_get_dialog_remote_target_uri(sip_dialog_t dialog,int * error)359 sip_get_dialog_remote_target_uri(sip_dialog_t dialog, int *error)
360 {
361 _sip_dialog_t *_dialog;
362 const struct sip_uri *rtarg = NULL;
363 const struct sip_value *val;
364
365 if (error != NULL)
366 *error = 0;
367 if (!sip_manage_dialog || dialog == NULL) {
368 if (error != NULL)
369 *error = EINVAL;
370 return (NULL);
371 }
372 _dialog = (_sip_dialog_t *)dialog;
373 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
374 if (dialog->sip_dlg_remote_target != NULL) {
375 val = sip_get_header_value(_dialog->sip_dlg_remote_target,
376 error);
377 if (val == NULL) {
378 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
379 return (NULL);
380 }
381 rtarg = val->sip_value_parse_uri;
382 }
383 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
384
385 return ((sip_uri_t)rtarg);
386 }
387
388 /*
389 * Return the dialog local contact uri.
390 */
391 const struct sip_uri *
sip_get_dialog_local_contact_uri(sip_dialog_t dialog,int * error)392 sip_get_dialog_local_contact_uri(sip_dialog_t dialog, int *error)
393 {
394 _sip_dialog_t *_dialog;
395 const struct sip_uri *lcuri = NULL;
396 const struct sip_value *val;
397
398 if (error != NULL)
399 *error = 0;
400 if (!sip_manage_dialog || dialog == NULL) {
401 if (error != NULL)
402 *error = EINVAL;
403 return (NULL);
404 }
405 _dialog = (_sip_dialog_t *)dialog;
406 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
407 if (dialog->sip_dlg_local_contact != NULL) {
408 val = sip_get_header_value(_dialog->sip_dlg_local_contact,
409 error);
410 if (val == NULL) {
411 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
412 return (NULL);
413 }
414 lcuri = val->sip_value_parse_uri;
415 }
416 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
417
418 return ((sip_uri_t)lcuri);
419 }
420
421 /*
422 * Return the dialog route set
423 */
424 const sip_str_t *
sip_get_dialog_route_set(sip_dialog_t dialog,int * error)425 sip_get_dialog_route_set(sip_dialog_t dialog, int *error)
426 {
427 _sip_dialog_t *_dialog;
428
429 if (error != NULL)
430 *error = 0;
431 if (!sip_manage_dialog || dialog == NULL) {
432 if (error != NULL)
433 *error = EINVAL;
434 return (NULL);
435 }
436 _dialog = (_sip_dialog_t *)dialog;
437 if (_dialog->sip_dlg_rset.sip_str_len > 0)
438 return (&_dialog->sip_dlg_rset);
439 return (NULL);
440 }
441
442 /*
443 * Return the dialog secure
444 */
445 boolean_t
sip_is_dialog_secure(sip_dialog_t dialog,int * error)446 sip_is_dialog_secure(sip_dialog_t dialog, int *error)
447 {
448 _sip_dialog_t *_dialog;
449 boolean_t issecure;
450
451 if (error != NULL)
452 *error = 0;
453 if (!sip_manage_dialog || dialog == NULL) {
454 if (error != NULL)
455 *error = EINVAL;
456 return (B_FALSE);
457 }
458 _dialog = (_sip_dialog_t *)dialog;
459 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
460 issecure = _dialog->sip_dlg_secure;
461 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
462 return (issecure);
463 }
464
465 /*
466 * Return the dialog local cseq
467 */
468 uint32_t
sip_get_dialog_local_cseq(sip_dialog_t dialog,int * error)469 sip_get_dialog_local_cseq(sip_dialog_t dialog, int *error)
470 {
471 _sip_dialog_t *_dialog;
472 uint32_t cseq;
473
474 if (error != NULL)
475 *error = 0;
476 if (!sip_manage_dialog || dialog == NULL) {
477 if (error != NULL)
478 *error = EINVAL;
479 return (0);
480 }
481 _dialog = (_sip_dialog_t *)dialog;
482 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
483 cseq = _dialog->sip_dlg_local_cseq;
484 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
485 return (cseq);
486 }
487
488 /*
489 * Return the dialog remote cseq
490 */
491 uint32_t
sip_get_dialog_remote_cseq(sip_dialog_t dialog,int * error)492 sip_get_dialog_remote_cseq(sip_dialog_t dialog, int *error)
493 {
494 _sip_dialog_t *_dialog;
495 uint32_t cseq;
496
497 if (error != NULL)
498 *error = 0;
499 if (!sip_manage_dialog || dialog == NULL) {
500 if (error != NULL)
501 *error = EINVAL;
502 return (0);
503 }
504 _dialog = (_sip_dialog_t *)dialog;
505 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
506 cseq = _dialog->sip_dlg_remote_cseq;
507 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
508 return (cseq);
509 }
510
511 /*
512 * Return the dialog type
513 */
514 int
sip_get_dialog_type(sip_dialog_t dialog,int * error)515 sip_get_dialog_type(sip_dialog_t dialog, int *error)
516 {
517 _sip_dialog_t *_dialog;
518 int type;
519
520 if (error != NULL)
521 *error = 0;
522 if (!sip_manage_dialog || dialog == NULL) {
523 if (error != NULL)
524 *error = EINVAL;
525 return (-1);
526 }
527 _dialog = (_sip_dialog_t *)dialog;
528 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
529 type = _dialog->sip_dlg_type;
530 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
531 return (type);
532 }
533
534 /*
535 * Return the number of messages exchanged within a dialog.
536 */
537 int
sip_get_dialog_msgcnt(sip_dialog_t dialog,int * error)538 sip_get_dialog_msgcnt(sip_dialog_t dialog, int *error)
539 {
540 _sip_dialog_t *_dialog;
541 int nmsgs;
542
543 if (error != NULL)
544 *error = 0;
545 if (!sip_manage_dialog || dialog == NULL) {
546 if (error != NULL)
547 *error = EINVAL;
548 return (-1);
549 }
550 _dialog = (_sip_dialog_t *)dialog;
551 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
552 nmsgs = _dialog->sip_dlg_msgcnt;
553 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
554 return (nmsgs);
555 }
556
557 /*
558 * Partial dialog ?
559 */
560 boolean_t
sip_incomplete_dialog(sip_dialog_t dialog)561 sip_incomplete_dialog(sip_dialog_t dialog)
562 {
563 _sip_dialog_t *_dialog;
564 boolean_t isnew;
565
566 if (!sip_manage_dialog || dialog == NULL)
567 return (B_FALSE);
568 _dialog = (_sip_dialog_t *)dialog;
569 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
570 isnew = _dialog->sip_dlg_state == SIP_DLG_NEW;
571 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
572 return (isnew);
573 }
574
575 /*
576 * Hold dialog
577 */
578 void
sip_hold_dialog(sip_dialog_t dialog)579 sip_hold_dialog(sip_dialog_t dialog)
580 {
581 _sip_dialog_t *_dialog;
582
583 if (!sip_manage_dialog || dialog == NULL)
584 return;
585 _dialog = (_sip_dialog_t *)dialog;
586 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
587 SIP_DLG_REFCNT_INCR(_dialog);
588 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
589 }
590
591 /*
592 * Release dialog
593 */
594 void
sip_release_dialog(sip_dialog_t dialog)595 sip_release_dialog(sip_dialog_t dialog)
596 {
597 _sip_dialog_t *_dialog;
598
599 if (!sip_manage_dialog || dialog == NULL)
600 return;
601 _dialog = (_sip_dialog_t *)dialog;
602 SIP_DLG_REFCNT_DECR(_dialog);
603 }
604
605 /*
606 * Delete a dialog
607 */
608 void
sip_delete_dialog(sip_dialog_t dialog)609 sip_delete_dialog(sip_dialog_t dialog)
610 {
611 if (!sip_manage_dialog || dialog == NULL)
612 return;
613 sip_dialog_terminate(dialog, NULL);
614 }
615