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 #include <stdio.h>
28 #include <stdlib.h>
29 #include <assert.h>
30 #include <errno.h>
31 #include <pthread.h>
32 #include <strings.h>
33 #include <sip.h>
34
35 #include "sip_msg.h"
36 #include "sip_miscdefs.h"
37 #include "sip_hash.h"
38 #include "sip_dialog.h"
39 #include "sip_parse_generic.h"
40
41 #define SIP_DLG_XCHG_FROM 0
42 #define SIP_DLG_XCHG_TO 1
43
44 /*
45 * Dialog state change callback function
46 */
47 void (*sip_dlg_ulp_state_cb)(sip_dialog_t, sip_msg_t, int, int) = NULL;
48 void (*sip_ulp_dlg_del_cb)(sip_dialog_t, sip_msg_t, void *) = NULL;
49
50 boolean_t sip_incomplete_dialog(sip_dialog_t);
51
52 /*
53 * Exchange From/To header
54 */
55 _sip_header_t *sip_dlg_xchg_from_to(sip_msg_t, int);
56
57 /*
58 * Complete dialog hash table
59 */
60 sip_hash_t sip_dialog_hash[SIP_HASH_SZ];
61
62 /*
63 * Partial dialog hash table
64 */
65 sip_hash_t sip_dialog_phash[SIP_HASH_SZ];
66
67 /*
68 * Route set structure
69 */
70 typedef struct sip_dlg_route_set_s {
71 char *sip_dlg_route;
72 sip_str_t sip_dlg_ruri;
73 boolean_t sip_dlg_route_lr;
74 struct sip_dlg_route_set_s *sip_dlg_route_next;
75 }sip_dlg_route_set_t;
76
77 sip_dialog_t sip_seed_dialog(sip_conn_object_t, _sip_msg_t *,
78 boolean_t, int);
79 sip_dialog_t sip_complete_dialog(_sip_msg_t *, _sip_dialog_t *);
80 int sip_dialog_process(_sip_msg_t *, sip_dialog_t *);
81 void sip_dialog_delete(_sip_dialog_t *);
82 void sip_dialog_init();
83 sip_dialog_t sip_dialog_find(_sip_msg_t *);
84 boolean_t sip_dialog_match(void *, void *);
85 boolean_t sip_dialog_free(void *, void *, int *);
86 sip_dialog_t sip_update_dialog(sip_dialog_t, _sip_msg_t *);
87 char *sip_dialog_req_uri(sip_dialog_t);
88
89 static void sip_release_dialog_res(_sip_dialog_t *);
90 void sip_dlg_self_destruct(void *);
91 static int sip_dialog_get_route_set(_sip_dialog_t *, _sip_msg_t *,
92 int);
93 static void sip_dialog_free_rset(sip_dlg_route_set_t *);
94
95 /*
96 * Timer object for partial dialogs
97 */
98 typedef struct sip_dialog_timer_obj_s {
99 _sip_dialog_t *dialog;
100 void (*func)(sip_dialog_t, sip_msg_t, void *);
101 } sip_dialog_timer_obj_t;
102
103 /*
104 * To avoid duplication all over the place
105 */
106 static void
sip_release_dialog_res(_sip_dialog_t * dialog)107 sip_release_dialog_res(_sip_dialog_t *dialog)
108 {
109 int count = 0;
110 sip_msg_chain_t *msg_chain;
111 sip_msg_chain_t *nmsg_chain;
112
113 if (dialog->sip_dlg_ref_cnt != 0) {
114 sip_write_to_log((void *)dialog, SIP_DIALOG_LOG |
115 SIP_ASSERT_ERROR, __FILE__, __LINE__);
116 }
117 assert(dialog->sip_dlg_ref_cnt == 0);
118 if (SIP_IS_TIMER_RUNNING(dialog->sip_dlg_timer))
119 SIP_CANCEL_TIMER(dialog->sip_dlg_timer);
120 if (dialog->sip_dlg_call_id != NULL)
121 sip_free_header(dialog->sip_dlg_call_id);
122 if (dialog->sip_dlg_local_uri_tag != NULL)
123 sip_free_header(dialog->sip_dlg_local_uri_tag);
124 if (dialog->sip_dlg_remote_uri_tag != NULL)
125 sip_free_header(dialog->sip_dlg_remote_uri_tag);
126 if (dialog->sip_dlg_remote_target != NULL)
127 sip_free_header(dialog->sip_dlg_remote_target);
128 if (dialog->sip_dlg_local_contact != NULL)
129 sip_free_header(dialog->sip_dlg_local_contact);
130 if (dialog->sip_dlg_new_local_contact != NULL)
131 sip_free_header(dialog->sip_dlg_new_local_contact);
132 if (dialog->sip_dlg_route_set != NULL)
133 sip_free_header(dialog->sip_dlg_route_set);
134 if (dialog->sip_dlg_event != NULL)
135 sip_free_header(dialog->sip_dlg_event);
136 if (dialog->sip_dlg_req_uri.sip_str_ptr != NULL) {
137 free(dialog->sip_dlg_req_uri.sip_str_ptr);
138 dialog->sip_dlg_req_uri.sip_str_ptr = NULL;
139 dialog->sip_dlg_req_uri.sip_str_len = 0;
140 }
141 if (dialog->sip_dlg_rset.sip_str_ptr != NULL) {
142 free(dialog->sip_dlg_rset.sip_str_ptr);
143 dialog->sip_dlg_rset.sip_str_len = 0;
144 dialog->sip_dlg_rset.sip_str_ptr = NULL;
145 }
146 for (count = 0; count <= SIP_DLG_DESTROYED; count++) {
147 msg_chain = dialog->sip_dlg_log[count].sip_msgs;
148 while (msg_chain != NULL) {
149 nmsg_chain = msg_chain->next;
150 if (msg_chain->sip_msg != NULL)
151 free(msg_chain->sip_msg);
152 free(msg_chain);
153 msg_chain = nmsg_chain;
154 }
155 }
156 (void) pthread_mutex_destroy(&dialog->sip_dlg_mutex);
157 free(dialog);
158 }
159
160 /*
161 * Get the route information from the 'value' and add it to the route
162 * set.
163 */
164 static sip_dlg_route_set_t *
sip_add_route_to_set(sip_hdr_value_t * value)165 sip_add_route_to_set(sip_hdr_value_t *value)
166 {
167 int vlen = 0;
168 sip_dlg_route_set_t *rset;
169 char *crlf;
170 const sip_param_t *uri_param;
171 int error;
172
173 rset = calloc(1, sizeof (*rset));
174 if (rset == NULL)
175 return (NULL);
176 rset->sip_dlg_route_next = NULL;
177 vlen = value->sip_value_end - value->sip_value_start;
178
179 /*
180 * check for CRLF
181 */
182 crlf = value->sip_value_end - strlen(SIP_CRLF);
183 while (crlf != NULL && strncmp(crlf, SIP_CRLF, strlen(SIP_CRLF)) == 0) {
184 vlen -= strlen(SIP_CRLF);
185 crlf -= strlen(SIP_CRLF);
186 }
187 rset->sip_dlg_route = calloc(1, vlen + 1);
188 if (rset->sip_dlg_route == NULL) {
189 free(rset);
190 return (NULL);
191 }
192 /*
193 * loose routing
194 */
195 rset->sip_dlg_route_lr = B_FALSE;
196 (void) strncpy(rset->sip_dlg_route, value->sip_value_start, vlen);
197 rset->sip_dlg_ruri.sip_str_ptr = rset->sip_dlg_route +
198 (value->cftr_uri.sip_str_ptr - value->sip_value_start);
199 rset->sip_dlg_ruri.sip_str_len = value->cftr_uri.sip_str_len;
200 rset->sip_dlg_route[vlen] = '\0';
201
202 assert(value->sip_value_parsed_uri != NULL);
203 /*
204 * Check if the 'lr' param is present for this route.
205 */
206 uri_param = sip_get_uri_params(value->sip_value_parsed_uri, &error);
207 if (error != 0) {
208 free(rset->sip_dlg_route);
209 free(rset);
210 return (NULL);
211 }
212 if (uri_param != NULL) {
213 rset->sip_dlg_route_lr = sip_is_param_present(uri_param, "lr",
214 strlen("lr"));
215 }
216 return (rset);
217 }
218
219 /*
220 * Depending on the route-set, determine the request URI.
221 */
222 char *
sip_dialog_req_uri(sip_dialog_t dialog)223 sip_dialog_req_uri(sip_dialog_t dialog)
224 {
225 const sip_str_t *req_uri;
226 char *uri;
227 _sip_dialog_t *_dialog;
228
229 _dialog = (_sip_dialog_t *)dialog;
230 if (_dialog->sip_dlg_route_set == NULL ||
231 _dialog->sip_dlg_req_uri.sip_str_ptr == NULL) {
232 const struct sip_value *val;
233
234 val = sip_get_header_value(_dialog->sip_dlg_remote_target,
235 NULL);
236 if (val == NULL)
237 return (NULL);
238 req_uri = &((sip_hdr_value_t *)val)->cftr_uri;
239 } else {
240 req_uri = &_dialog->sip_dlg_req_uri;
241 }
242 uri = (char *)malloc(req_uri->sip_str_len + 1);
243 if (uri == NULL)
244 return (NULL);
245 (void) strncpy(uri, req_uri->sip_str_ptr, req_uri->sip_str_len);
246 uri[req_uri->sip_str_len] = '\0';
247
248 return (uri);
249 }
250
251 /*
252 * Free the route set.
253 */
254 void
sip_dialog_free_rset(sip_dlg_route_set_t * rset)255 sip_dialog_free_rset(sip_dlg_route_set_t *rset)
256 {
257 sip_dlg_route_set_t *next;
258
259 while (rset != NULL) {
260 next = rset->sip_dlg_route_next;
261 rset->sip_dlg_route_next = NULL;
262 free(rset->sip_dlg_route);
263 free(rset);
264 rset = next;
265 }
266 }
267
268 /*
269 * Recompute route-set
270 */
271 static int
sip_dlg_recompute_rset(_sip_dialog_t * dialog,_sip_msg_t * sip_msg,int what)272 sip_dlg_recompute_rset(_sip_dialog_t *dialog, _sip_msg_t *sip_msg, int what)
273 {
274 int ret;
275
276 if (dialog->sip_dlg_route_set != NULL) {
277 sip_free_header(dialog->sip_dlg_route_set);
278 dialog->sip_dlg_route_set = NULL;
279 }
280 if (dialog->sip_dlg_req_uri.sip_str_ptr != NULL) {
281 free(dialog->sip_dlg_req_uri.sip_str_ptr);
282 dialog->sip_dlg_req_uri.sip_str_ptr = NULL;
283 dialog->sip_dlg_req_uri.sip_str_len = 0;
284 }
285 if (dialog->sip_dlg_rset.sip_str_ptr != NULL) {
286 free(dialog->sip_dlg_rset.sip_str_ptr);
287 dialog->sip_dlg_rset.sip_str_ptr = NULL;
288 dialog->sip_dlg_rset.sip_str_len = 0;
289 }
290 ret = sip_dialog_get_route_set(dialog, sip_msg, what);
291 return (ret);
292 }
293
294 /*
295 * If the route set is empty, the UAC MUST place the remote target URI
296 * into the Request-URI. The UAC MUST NOT add a Route header field to
297 * the request.
298 *
299 * If the route set is not empty, and the first URI in the route set
300 * contains the lr parameter (see Section 19.1.1), the UAC MUST place
301 * the remote target URI into the Request-URI and MUST include a Route
302 * header field containing the route set values in order, including all
303 * parameters.
304 *
305 * If the route set is not empty, and its first URI does not contain the
306 * lr parameter, the UAC MUST place the first URI from the route set
307 * into the Request-URI, stripping any parameters that are not allowed
308 * in a Request-URI. The UAC MUST add a Route header field containing
309 * the remainder of the route set values in order, including all
310 * parameters. The UAC MUST then place the remote target URI into the
311 * Route header field as the last value.
312 */
313 int
sip_dialog_set_route_hdr(_sip_dialog_t * dialog,sip_dlg_route_set_t * rset_head,int rcnt,int rlen)314 sip_dialog_set_route_hdr(_sip_dialog_t *dialog, sip_dlg_route_set_t *rset_head,
315 int rcnt, int rlen)
316 {
317 size_t rset_len;
318 _sip_header_t *rhdr;
319 char *rset;
320 char *rp;
321 char *rsp;
322 int count;
323 sip_dlg_route_set_t *route;
324 boolean_t first = B_TRUE;
325 const sip_str_t *to_uri;
326 char *uri = NULL;
327 int rspl;
328 int rpl;
329
330 if (rcnt <= 0) {
331 sip_write_to_log((void *)dialog, SIP_DIALOG_LOG |
332 SIP_ASSERT_ERROR, __FILE__, __LINE__);
333 }
334 assert(rcnt > 0);
335
336 dialog->sip_dlg_rset.sip_str_len = rlen + rcnt - 1;
337 dialog->sip_dlg_rset.sip_str_ptr = malloc(rlen + rcnt);
338 if (dialog->sip_dlg_rset.sip_str_ptr == NULL)
339 return (ENOMEM);
340 rsp = dialog->sip_dlg_rset.sip_str_ptr;
341 rspl = rlen + rcnt;
342 route = rset_head;
343 rset_len = rlen;
344 if (!route->sip_dlg_route_lr) {
345 const struct sip_value *val;
346
347 val = sip_get_header_value(dialog->sip_dlg_remote_target, NULL);
348 to_uri = &((sip_hdr_value_t *)val)->cftr_uri;
349 uri = (char *)malloc(to_uri->sip_str_len + 1);
350 if (uri == NULL) {
351 free(dialog->sip_dlg_rset.sip_str_ptr);
352 dialog->sip_dlg_rset.sip_str_len = 0;
353 dialog->sip_dlg_rset.sip_str_ptr = NULL;
354 return (ENOMEM);
355 }
356 (void) strncpy(uri, to_uri->sip_str_ptr, to_uri->sip_str_len);
357 uri[to_uri->sip_str_len] = '\0';
358 rset_len = rlen - strlen(route->sip_dlg_route) + strlen(uri) +
359 SIP_SPACE_LEN + sizeof (char) + SIP_SPACE_LEN +
360 sizeof (char);
361 count = snprintf(rsp, rspl, "%s", route->sip_dlg_route);
362 dialog->sip_dlg_req_uri.sip_str_ptr = malloc(
363 route->sip_dlg_ruri.sip_str_len + 1);
364 if (dialog->sip_dlg_req_uri.sip_str_ptr == NULL) {
365 free(uri);
366 free(dialog->sip_dlg_rset.sip_str_ptr);
367 dialog->sip_dlg_rset.sip_str_len = 0;
368 dialog->sip_dlg_rset.sip_str_ptr = NULL;
369 return (ENOMEM);
370 }
371 (void) strncpy(dialog->sip_dlg_req_uri.sip_str_ptr, rsp +
372 (route->sip_dlg_ruri.sip_str_ptr - route->sip_dlg_route),
373 route->sip_dlg_ruri.sip_str_len);
374 dialog->sip_dlg_req_uri.sip_str_ptr[
375 route->sip_dlg_ruri.sip_str_len] = '\0';
376 dialog->sip_dlg_req_uri.sip_str_len =
377 route->sip_dlg_ruri.sip_str_len;
378
379 rsp += count;
380 rspl -= count;
381 route = route->sip_dlg_route_next;
382 }
383
384 /*
385 * rcnt - 1 is for the number of COMMAs
386 */
387 rset_len += strlen(SIP_ROUTE) + SIP_SPACE_LEN + sizeof (char) +
388 SIP_SPACE_LEN + rcnt - 1;
389 rset = malloc(rset_len + 1);
390 if (rset == NULL) {
391 free(dialog->sip_dlg_rset.sip_str_ptr);
392 dialog->sip_dlg_rset.sip_str_len = 0;
393 dialog->sip_dlg_rset.sip_str_ptr = NULL;
394 return (ENOMEM);
395 }
396 rhdr = sip_new_header(rset_len + strlen(SIP_CRLF));
397 if (rhdr == NULL) {
398 free(rset);
399 free(dialog->sip_dlg_rset.sip_str_ptr);
400 dialog->sip_dlg_rset.sip_str_len = 0;
401 dialog->sip_dlg_rset.sip_str_ptr = NULL;
402 return (ENOMEM);
403 }
404
405 rp = rset;
406 rpl = rset_len + 1;
407 count = snprintf(rp, rpl, "%s %c ", SIP_ROUTE, SIP_HCOLON);
408 rp += count;
409 rpl -= count;
410
411 while (route != NULL) {
412 if (first) {
413 count = snprintf(rp, rpl, "%s", route->sip_dlg_route);
414 rp += count;
415 rpl -= count;
416 first = B_FALSE;
417 if (uri != NULL) {
418 count = snprintf(rsp, rspl, "%c%s",
419 SIP_COMMA, route->sip_dlg_route);
420 } else {
421 count = snprintf(rsp, rspl, "%s",
422 route->sip_dlg_route);
423 }
424 rsp += count;
425 rspl -= count;
426 } else {
427 count = snprintf(rp, rpl, "%c%s", SIP_COMMA,
428 route->sip_dlg_route);
429 rp += count;
430 rpl -= count;
431 count = snprintf(rsp, rspl, "%c%s", SIP_COMMA,
432 route->sip_dlg_route);
433 rsp += count;
434 rspl -= count;
435 }
436 route = route->sip_dlg_route_next;
437 }
438 if (rsp > dialog->sip_dlg_rset.sip_str_ptr +
439 dialog->sip_dlg_rset.sip_str_len) {
440 sip_write_to_log((void *)dialog, SIP_DIALOG_LOG |
441 SIP_ASSERT_ERROR, __FILE__, __LINE__);
442 }
443 assert(rsp <= dialog->sip_dlg_rset.sip_str_ptr +
444 dialog->sip_dlg_rset.sip_str_len);
445 dialog->sip_dlg_rset.sip_str_ptr[dialog->sip_dlg_rset.sip_str_len] =
446 '\0';
447 if (uri != NULL) {
448 if (first) {
449 count = snprintf(rp, rpl, "%c %s %c", SIP_LAQUOT,
450 uri, SIP_RAQUOT);
451 } else {
452 count = snprintf(rp, rpl, "%c%c %s %c", SIP_COMMA,
453 SIP_LAQUOT, uri, SIP_RAQUOT);
454 }
455 rp += count;
456 rpl -= count;
457 free(uri);
458 }
459 if (rp > rset + rset_len) {
460 sip_write_to_log((void *)dialog, SIP_DIALOG_LOG |
461 SIP_ASSERT_ERROR, __FILE__, __LINE__);
462 }
463 assert(rp <= rset + rset_len);
464 (void) snprintf(rhdr->sip_hdr_start, rset_len + strlen(SIP_CRLF) + 1,
465 "%s%s", rset, SIP_CRLF);
466 free(rset);
467 dialog->sip_dlg_route_set = (sip_header_t)rhdr;
468 sip_dialog_free_rset(rset_head);
469 return (0);
470 }
471
472 /*
473 * UAC Behavior
474 * The route set MUST be set to the list of URIs in the Record-Route
475 * header field from the response, taken in reverse order and preserving
476 * all URI parameters.
477 *
478 * UAS behavior
479 * The route set MUST be set to the list of URIs in the Record-Route
480 * header field from the request, taken in order and preserving all URI
481 * parameters.
482 */
483 static int
sip_dialog_get_route_set(_sip_dialog_t * dialog,_sip_msg_t * sip_msg,int what)484 sip_dialog_get_route_set(_sip_dialog_t *dialog, _sip_msg_t *sip_msg, int what)
485 {
486 sip_header_t rrhdr;
487 sip_hdr_value_t *value;
488 int error;
489 sip_dlg_route_set_t *rset_head = NULL;
490 sip_dlg_route_set_t *rset_tail = NULL;
491 sip_dlg_route_set_t *rset;
492 int rset_cnt = 0;
493 int rset_len = 0;
494
495 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
496 rrhdr = sip_search_for_header(sip_msg, SIP_RECORD_ROUTE, NULL);
497 while (rrhdr != NULL) {
498 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
499 value = (sip_hdr_value_t *)sip_get_header_value(rrhdr, &error);
500 while (value != NULL && error == 0) {
501 char *crlf;
502
503 if (value->sip_value_state == SIP_VALUE_BAD) {
504 value = (sip_hdr_value_t *)sip_get_next_value(
505 (sip_header_value_t)value, &error);
506 continue;
507 }
508 rset = sip_add_route_to_set(value);
509 if (rset == NULL)
510 goto r_error;
511 /*
512 * Add one for COMMA
513 */
514 rset_cnt++;
515 rset_len += (value->sip_value_end -
516 value->sip_value_start);
517 /*
518 * Check for CRLF
519 */
520 crlf = value->sip_value_end - strlen(SIP_CRLF);
521 while (crlf != NULL &&
522 strncmp(crlf, SIP_CRLF, strlen(SIP_CRLF)) == 0) {
523 rset_len -= strlen(SIP_CRLF);
524 crlf -= strlen(SIP_CRLF);
525 }
526 if (rset_head == NULL) {
527 if (rset_tail != NULL) {
528 sip_write_to_log((void *)dialog,
529 SIP_DIALOG_LOG | SIP_ASSERT_ERROR,
530 __FILE__, __LINE__);
531 }
532 assert(rset_tail == NULL);
533 rset_head = rset_tail = rset;
534 } else if (what == SIP_UAS_DIALOG) {
535 rset_tail->sip_dlg_route_next = rset;
536 rset_tail = rset;
537 } else if (what == SIP_UAC_DIALOG) {
538 rset->sip_dlg_route_next = rset_head;
539 rset_head = rset;
540 } else {
541 sip_write_to_log((void *)dialog,
542 SIP_DIALOG_LOG | SIP_ASSERT_ERROR,
543 __FILE__, __LINE__);
544 assert(0);
545 }
546 value = (sip_hdr_value_t *)sip_get_next_value(
547 (sip_header_value_t)value, &error);
548 }
549 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
550 rrhdr = sip_search_for_header(sip_msg, SIP_RECORD_ROUTE, rrhdr);
551 }
552 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
553 if (rset_cnt == 0)
554 return (0);
555 if (sip_dialog_set_route_hdr(dialog, rset_head, rset_cnt,
556 rset_len) != 0) {
557 goto r_error;
558 }
559 return (0);
560 r_error:
561 sip_dialog_free_rset(rset_head);
562 return (ENOMEM);
563 }
564
565 /*
566 * UAS behavior:
567 * The remote sequence number MUST be set to the value of the sequence
568 * number in the CSeq header field of the request. The local sequence
569 * number MUST be empty. The call identifier component of the dialog ID
570 * MUST be set to the value of the Call-ID in the request. The local
571 * tag component of the dialog ID MUST be set to the tag in the To field
572 * in the response to the request (which always includes a tag), and the
573 * remote tag component of the dialog ID MUST be set to the tag from the
574 * From field in the request. A UAS MUST be prepared to receive a
575 * request without a tag in the From field, in which case the tag is
576 * considered to have a value of null.
577 * The remote URI MUST be set to the URI in the From field, and the
578 * local URI MUST be set to the URI in the To field.
579 * The remote target MUST be set to the URI from the Contact header field
580 * of the request.
581 *
582 * UAC behavior:
583 * The local sequence number MUST be set to the value of the sequence
584 * number in the CSeq header field of the request. The remote sequence
585 * number MUST be empty (it is established when the remote UA sends a
586 * request within the dialog). The call identifier component of the
587 * dialog ID MUST be set to the value of the Call-ID in the request.
588 * The local tag component of the dialog ID MUST be set to the tag in
589 * the From field in the request, and the remote tag component of the
590 * dialog ID MUST be set to the tag in the To field of the response. A
591 * UAC MUST be prepared to receive a response without a tag in the To
592 * field, in which case the tag is considered to have a value of null.
593 * The remote URI MUST be set to the URI in the To field, and the local
594 * URI MUST be set to the URI in the From field.
595 * The remote target MUST be set to the URI from the Contact header field
596 * of the response.
597 */
598
599
600 /*
601 * This is the routine that seeds a dialog.
602 */
603 sip_dialog_t
sip_seed_dialog(sip_conn_object_t obj,_sip_msg_t * sip_msg,boolean_t dlg_on_fork,int dlg_type)604 sip_seed_dialog(sip_conn_object_t obj, _sip_msg_t *sip_msg,
605 boolean_t dlg_on_fork, int dlg_type)
606 {
607 _sip_dialog_t *dialog;
608 int cseq;
609 sip_header_t fhdr = NULL;
610 sip_header_t thdr = NULL;
611 sip_header_t chdr;
612 sip_header_t cihdr;
613 sip_header_t evhdr = NULL;
614 const struct sip_value *value;
615 sip_dialog_timer_obj_t *tim_obj = NULL;
616 const sip_str_t *callid;
617 sip_method_t method;
618 int timer1 = sip_timer_T1;
619 int error;
620
621 if (!sip_msg_is_request((sip_msg_t)sip_msg, &error))
622 return (NULL);
623
624 method = sip_get_request_method((sip_msg_t)sip_msg, &error);
625 /*
626 * Only INVITE and SUBSCRIBE supported
627 */
628 if (error != 0 || (method != INVITE && method != SUBSCRIBE))
629 return (NULL);
630
631 /*
632 * A request outside of a dialog MUST NOT contain a To tag
633 */
634 if (sip_get_to_tag((sip_msg_t)sip_msg, NULL) != NULL)
635 return (NULL);
636
637 if (dlg_type == SIP_UAS_DIALOG) {
638 thdr = sip_dlg_xchg_from_to((sip_msg_t)sip_msg,
639 SIP_DLG_XCHG_FROM);
640 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
641 } else {
642 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
643 fhdr = sip_search_for_header(sip_msg, SIP_FROM, NULL);
644 }
645 cihdr = sip_search_for_header(sip_msg, SIP_CALL_ID, NULL);
646 chdr = sip_search_for_header(sip_msg, SIP_CONTACT, NULL);
647 if (method == SUBSCRIBE)
648 evhdr = sip_search_for_header(sip_msg, SIP_EVENT, NULL);
649 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
650 if ((fhdr == NULL && thdr == NULL) || cihdr == NULL || chdr == NULL ||
651 (method == SUBSCRIBE && evhdr == NULL)) {
652 if (thdr != NULL)
653 sip_free_header(thdr);
654 return (NULL);
655 }
656
657 /*
658 * Sanity check since we just store the headers in the dialog
659 */
660 if (sip_get_from_tag((sip_msg_t)sip_msg, NULL) == NULL ||
661 sip_get_from_uri_str((sip_msg_t)sip_msg, NULL) == NULL ||
662 ((cseq = sip_get_callseq_num((sip_msg_t)sip_msg, NULL)) == -1) ||
663 (callid = sip_get_callid((sip_msg_t)sip_msg, NULL)) == NULL ||
664 sip_get_to_uri_str((sip_msg_t)sip_msg, NULL) == NULL ||
665 ((value = sip_get_header_value(chdr, NULL)) == NULL) ||
666 sip_get_contact_uri_str((sip_header_value_t)value, NULL) == NULL) {
667 if (thdr != NULL)
668 sip_free_header(thdr);
669 return (NULL);
670 }
671
672 tim_obj = calloc(1, sizeof (sip_dialog_timer_obj_t));
673 if (tim_obj == NULL) {
674 if (thdr != NULL)
675 sip_free_header(thdr);
676 return (NULL);
677 }
678 dialog = calloc(1, sizeof (_sip_dialog_t));
679 if (dialog == NULL) {
680 if (thdr != NULL)
681 sip_free_header(thdr);
682 return (NULL);
683 }
684 /*
685 * We will take the TO header with the tag when we complete this
686 * dialog
687 */
688 if (dlg_type == SIP_UAS_DIALOG) {
689 dialog->sip_dlg_remote_uri_tag = thdr;
690 /*
691 * We take the remote target from the incoming request on the
692 * UAS. For the UAC, we will take it from the response.
693 */
694 if ((dialog->sip_dlg_remote_target = sip_dup_header(chdr)) ==
695 NULL) {
696 goto dia_err;
697 }
698 } else {
699 if ((dialog->sip_dlg_local_uri_tag = sip_dup_header(fhdr)) ==
700 NULL) {
701 goto dia_err;
702 }
703 /*
704 * We take the local contact from the originating request on
705 * UAC. For the UAS, we will take it from the response.
706 */
707 if ((dialog->sip_dlg_local_contact = sip_dup_header(chdr)) ==
708 NULL) {
709 goto dia_err;
710 } else {
711 dialog->sip_dlg_new_local_contact = NULL;
712 }
713 }
714 if ((dialog->sip_dlg_call_id = sip_dup_header(cihdr)) == NULL)
715 goto dia_err;
716 if (method == SUBSCRIBE) {
717 dialog->sip_dlg_event = sip_dup_header(evhdr);
718 if (dialog->sip_dlg_event == NULL) {
719 goto dia_err;
720 }
721 }
722 dialog->sip_dlg_rset.sip_str_ptr = NULL;
723 dialog->sip_dlg_rset.sip_str_len = 0;
724 dialog->sip_dlg_req_uri.sip_str_ptr = NULL;
725 dialog->sip_dlg_req_uri.sip_str_len = 0;
726 /*
727 * Get the route set from the request, if present
728 */
729 if (dlg_type == SIP_UAS_DIALOG &&
730 sip_dialog_get_route_set(dialog, sip_msg, dlg_type) != 0) {
731 goto dia_err;
732 }
733 if (dlg_type == SIP_UAC_DIALOG)
734 dialog->sip_dlg_local_cseq = cseq;
735 else
736 dialog->sip_dlg_remote_cseq = cseq;
737 dialog->sip_dlg_type = dlg_type;
738 dialog->sip_dlg_on_fork = dlg_on_fork;
739 dialog->sip_dlg_method = method;
740 /*
741 * Set the partial dialog timer with the INVITE timeout val
742 */
743 if (sip_conn_timer1 != NULL)
744 timer1 = sip_conn_timer1(obj);
745 SIP_INIT_TIMER(dialog->sip_dlg_timer, 64 * timer1);
746 tim_obj->dialog = dialog;
747 /*
748 * Since at the client we never pass the partial dialog, we need not
749 * invoke the callback when the partial dialog self-destructs.
750 */
751 if (dlg_type == SIP_UAS_DIALOG)
752 tim_obj->func = sip_ulp_dlg_del_cb;
753 SIP_SCHED_TIMER(dialog->sip_dlg_timer, (void *)tim_obj,
754 sip_dlg_self_destruct);
755 if (!SIP_IS_TIMER_RUNNING(dialog->sip_dlg_timer))
756 goto dia_err;
757 (void) pthread_mutex_init(&dialog->sip_dlg_mutex, NULL);
758
759 if (dlg_type == SIP_UAC_DIALOG) {
760 const sip_str_t *local_tag;
761
762 local_tag = sip_get_from_tag((sip_msg_t)sip_msg, NULL);
763 if (local_tag == NULL) {
764 sip_write_to_log((void *)dialog, SIP_DIALOG_LOG |
765 SIP_ASSERT_ERROR, __FILE__, __LINE__);
766 }
767 assert(local_tag != NULL);
768 sip_md5_hash(local_tag->sip_str_ptr, local_tag->sip_str_len,
769 callid->sip_str_ptr, callid->sip_str_len,
770 NULL, 0, NULL, 0, NULL, 0, NULL, 0,
771 (uchar_t *)dialog->sip_dlg_id);
772
773
774 /*
775 * Add it to the partial hash table
776 */
777 if (sip_hash_add(sip_dialog_phash, (void *)dialog,
778 SIP_DIGEST_TO_HASH(dialog->sip_dlg_id)) != 0) {
779 goto dia_err;
780 }
781 }
782
783 dialog->sip_dlg_msgcnt = 1;
784 sip_add_log(&dialog->sip_dlg_log[dialog->sip_dlg_state],
785 (sip_msg_t)sip_msg, dialog->sip_dlg_msgcnt, SIP_DIALOG_LOG);
786
787 SIP_DLG_REFCNT_INCR(dialog);
788 return ((sip_dialog_t)dialog);
789 dia_err:
790 sip_release_dialog_res(dialog);
791 if (SIP_IS_TIMER_RUNNING(dialog->sip_dlg_timer))
792 SIP_CANCEL_TIMER(dialog->sip_dlg_timer);
793 if (tim_obj != NULL)
794 free(tim_obj);
795 return (NULL);
796 }
797
798 /*
799 * When creating a dialog from a NOTIFY request, we need to get the FROM
800 * header for the dialog from the TO header of the NOTIFY.
801 */
802 _sip_header_t *
sip_dlg_xchg_from_to(sip_msg_t sip_msg,int what)803 sip_dlg_xchg_from_to(sip_msg_t sip_msg, int what)
804 {
805 int len;
806 _sip_header_t *newhdr;
807 int cnt;
808 const struct sip_header *hdr;
809 int hdrsize;
810 int error;
811
812 hdr = sip_get_header(sip_msg, what == SIP_DLG_XCHG_FROM ? SIP_FROM :
813 SIP_TO, NULL, &error);
814 if (error != 0 || hdr == NULL)
815 return (NULL);
816 if (sip_parse_goto_values((_sip_header_t *)hdr) != 0)
817 return (NULL);
818 len = hdr->sip_hdr_end - hdr->sip_hdr_current;
819 if (what == SIP_DLG_XCHG_FROM) {
820 hdrsize = len + strlen(SIP_TO) + SIP_SPACE_LEN + sizeof (char) +
821 SIP_SPACE_LEN;
822 } else {
823 hdrsize = len + strlen(SIP_FROM) + SIP_SPACE_LEN +
824 sizeof (char) + SIP_SPACE_LEN;
825 }
826 newhdr = sip_new_header(hdrsize);
827 if (newhdr == NULL)
828 return (NULL);
829 if (what == SIP_DLG_XCHG_FROM) {
830 cnt = snprintf(newhdr->sip_hdr_current, hdrsize + 1,
831 "%s %c ", SIP_TO, SIP_HCOLON);
832 } else {
833 cnt = snprintf(newhdr->sip_hdr_current, hdrsize + 1,
834 "%s %c ", SIP_FROM, SIP_HCOLON);
835 }
836 newhdr->sip_hdr_current += cnt;
837 (void) strncpy(newhdr->sip_hdr_current, hdr->sip_hdr_current, len);
838 newhdr->sip_hdr_current += len;
839 assert(newhdr->sip_hdr_current == newhdr->sip_hdr_end);
840 assert(hdr->sip_header_functions != NULL);
841
842 /*
843 * FROM and TO have common parsing functions
844 */
845 newhdr->sip_header_functions = hdr->sip_header_functions;
846 newhdr->sip_hdr_current = newhdr->sip_hdr_start;
847
848 return (newhdr);
849 }
850
851 /*
852 * This is the response that completes the dialog that was created
853 * in sip_seed_dialog().
854 */
855 sip_dialog_t
sip_complete_dialog(_sip_msg_t * sip_msg,_sip_dialog_t * dialog)856 sip_complete_dialog(_sip_msg_t *sip_msg, _sip_dialog_t *dialog)
857 {
858 _sip_header_t *thdr;
859 _sip_header_t *evhdr = NULL;
860 _sip_header_t *substate = NULL;
861 sip_header_t chdr = NULL;
862 int resp_code;
863 const sip_str_t *ttag;
864 const sip_str_t *remtag;
865 const sip_str_t *callid;
866 const struct sip_value *val;
867 sip_method_t method;
868 int error = 0;
869 int prev_state;
870 boolean_t alloc_thdr = B_FALSE;
871
872 if (sip_msg_is_request((sip_msg_t)sip_msg, &error) && error == 0)
873 method = sip_get_request_method((sip_msg_t)sip_msg, &error);
874 else
875 method = sip_get_callseq_method((sip_msg_t)sip_msg, &error);
876 if (error != 0 || dialog == NULL ||
877 (sip_msg_is_request((sip_msg_t)sip_msg, &error) &&
878 (dialog->sip_dlg_method == INVITE || method != NOTIFY))) {
879 return (NULL);
880 }
881 if ((dialog->sip_dlg_type == SIP_UAC_DIALOG && method != NOTIFY &&
882 sip_get_callseq_num((sip_msg_t)sip_msg, NULL) !=
883 dialog->sip_dlg_local_cseq) ||
884 (dialog->sip_dlg_type == SIP_UAS_DIALOG && method != NOTIFY &&
885 sip_get_callseq_num((sip_msg_t)sip_msg, NULL) !=
886 dialog->sip_dlg_remote_cseq)) {
887 return (NULL);
888 }
889 if (method == NOTIFY) {
890 const sip_str_t *sstate;
891
892 thdr = sip_dlg_xchg_from_to((sip_msg_t)sip_msg,
893 SIP_DLG_XCHG_FROM);
894 if (thdr == NULL)
895 return (NULL);
896 alloc_thdr = B_TRUE;
897 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
898 chdr = sip_search_for_header(sip_msg, SIP_CONTACT, NULL);
899 if (chdr == NULL) {
900 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
901 sip_free_header(thdr);
902 return (NULL);
903 }
904 evhdr = sip_search_for_header(sip_msg, SIP_EVENT, NULL);
905 if (evhdr == NULL) {
906 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
907 sip_free_header(thdr);
908 return (NULL);
909 }
910 substate = sip_search_for_header(sip_msg,
911 SIP_SUBSCRIPTION_STATE, NULL);
912 if (substate == NULL) {
913 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
914 sip_free_header(thdr);
915 return (NULL);
916 }
917 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
918 sstate = sip_get_substate((sip_msg_t)sip_msg, &error);
919 if (sstate == NULL || error != 0) {
920 sip_free_header(thdr);
921 return (NULL);
922 }
923 if ((sstate->sip_str_len != strlen("pending") &&
924 sstate->sip_str_len != strlen("active")) ||
925 ((sstate->sip_str_len == strlen("pending") &&
926 strncasecmp(sstate->sip_str_ptr, "pending",
927 strlen("pending")) != 0) ||
928 (sstate->sip_str_len == strlen("active") &&
929 strncasecmp(sstate->sip_str_ptr, "active",
930 strlen("active")) != 0))) {
931 sip_free_header(thdr);
932 return (NULL);
933 }
934 ttag = sip_get_from_tag((sip_msg_t)sip_msg, NULL);
935 } else {
936 if (dialog->sip_dlg_type == SIP_UAS_DIALOG) {
937 thdr = sip_dlg_xchg_from_to((sip_msg_t)sip_msg,
938 SIP_DLG_XCHG_TO);
939 alloc_thdr = B_TRUE;
940 } else {
941 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
942 thdr = sip_search_for_header(sip_msg, SIP_TO, NULL);
943 if (dialog->sip_dlg_remote_target == NULL) {
944 chdr = sip_search_for_header(sip_msg,
945 SIP_CONTACT, NULL);
946 }
947 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
948 }
949 if (thdr == NULL) {
950 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
951 return (NULL);
952 }
953 ttag = sip_get_to_tag((sip_msg_t)sip_msg, NULL);
954 }
955 if (ttag == NULL) {
956 if (alloc_thdr)
957 sip_free_header(thdr);
958 return (NULL);
959 }
960 prev_state = dialog->sip_dlg_state;
961
962 if (method == NOTIFY) {
963 int error;
964 const sip_str_t *dlg_id_val = NULL;
965 const sip_str_t *event;
966 const sip_str_t *id_val = NULL;
967 sip_header_value_t ev_val;
968 sip_hdr_value_t *dlg_ev_val = NULL;
969
970 event = sip_get_event((sip_msg_t)sip_msg, &error);
971 if (event == NULL || error != 0) {
972 sip_free_header(thdr);
973 return (NULL);
974 }
975 ev_val = (sip_header_value_t)sip_get_header_value(evhdr,
976 &error);
977 if (ev_val != NULL)
978 id_val = sip_get_param_value(ev_val, "id", &error);
979 if (error == 0) {
980 dlg_ev_val = (sip_hdr_value_t *)sip_get_header_value(
981 dialog->sip_dlg_event, &error);
982 }
983 if (dlg_ev_val == NULL || error != 0) {
984 sip_free_header(thdr);
985 return (NULL);
986 }
987 dlg_id_val = sip_get_param_value((sip_header_value_t)dlg_ev_val,
988 "id", &error);
989 if (error != 0 ||
990 dlg_ev_val->str_val_len != event->sip_str_len ||
991 strncmp(dlg_ev_val->str_val_ptr, event->sip_str_ptr,
992 event->sip_str_len != 0)) {
993 sip_free_header(thdr);
994 return (NULL);
995 }
996 if ((dlg_id_val == NULL && id_val != NULL) ||
997 (dlg_id_val != NULL && id_val == NULL)) {
998 sip_free_header(thdr);
999 return (NULL);
1000 } else if (dlg_id_val != NULL && id_val != NULL) {
1001 if (dlg_id_val->sip_str_len != id_val->sip_str_len ||
1002 strncasecmp(dlg_id_val->sip_str_ptr,
1003 id_val->sip_str_ptr, dlg_id_val->sip_str_len) !=
1004 0) {
1005 sip_free_header(thdr);
1006 return (NULL);
1007 }
1008 }
1009 if (dialog->sip_dlg_type == SIP_UAC_DIALOG) {
1010 dialog->sip_dlg_remote_uri_tag = thdr;
1011 if ((dialog->sip_dlg_remote_target =
1012 sip_dup_header(chdr)) == NULL) {
1013 sip_free_header(thdr);
1014 return (NULL);
1015 }
1016 } else {
1017 dialog->sip_dlg_local_uri_tag = thdr;
1018 }
1019 dialog->sip_dlg_state = SIP_DLG_CONFIRMED;
1020 } else {
1021 resp_code = sip_get_response_code((sip_msg_t)sip_msg, &error);
1022 (void) pthread_mutex_lock(&dialog->sip_dlg_mutex);
1023 if (dialog->sip_dlg_state != SIP_DLG_NEW) {
1024 sip_write_to_log((void *)dialog, SIP_DIALOG_LOG |
1025 SIP_ASSERT_ERROR, __FILE__, __LINE__);
1026 }
1027 assert(dialog->sip_dlg_state == SIP_DLG_NEW);
1028 if (dialog->sip_dlg_remote_target == NULL && chdr != NULL) {
1029 if (dialog->sip_dlg_type != SIP_UAC_DIALOG) {
1030 sip_write_to_log((void *)dialog,
1031 SIP_DIALOG_LOG | SIP_ASSERT_ERROR,
1032 __FILE__, __LINE__);
1033 }
1034 assert(dialog->sip_dlg_type == SIP_UAC_DIALOG);
1035 if ((dialog->sip_dlg_remote_target =
1036 sip_dup_header(chdr)) == NULL) {
1037 (void) pthread_mutex_unlock(
1038 &dialog->sip_dlg_mutex);
1039 if (alloc_thdr)
1040 sip_free_header(thdr);
1041 goto terminate_new_dlg;
1042 }
1043 if (sip_dialog_get_route_set(dialog, sip_msg,
1044 dialog->sip_dlg_type) != 0) {
1045 (void) pthread_mutex_unlock(
1046 &dialog->sip_dlg_mutex);
1047 if (alloc_thdr)
1048 sip_free_header(thdr);
1049 goto terminate_new_dlg;
1050 }
1051 }
1052 if (SIP_PROVISIONAL_RESP(resp_code)) {
1053 dialog->sip_dlg_state = SIP_DLG_EARLY;
1054 } else if (SIP_OK_RESP(resp_code)) {
1055 /*
1056 * Per 12.1 the UAS must include the contact header
1057 * for a dialog establishing response, so if we
1058 * don't find one, we terminate it.
1059 */
1060 if (dialog->sip_dlg_remote_target == NULL) {
1061 (void) pthread_mutex_unlock(
1062 &dialog->sip_dlg_mutex);
1063 if (sip_ulp_dlg_del_cb != NULL) {
1064 sip_ulp_dlg_del_cb(dialog,
1065 (sip_msg_t)sip_msg, NULL);
1066 }
1067 if (alloc_thdr)
1068 sip_free_header(thdr);
1069 goto terminate_new_dlg;
1070 }
1071 dialog->sip_dlg_state = SIP_DLG_CONFIRMED;
1072 } else {
1073 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1074 if (sip_ulp_dlg_del_cb != NULL) {
1075 sip_ulp_dlg_del_cb(dialog, (sip_msg_t)sip_msg,
1076 NULL);
1077 }
1078 if (alloc_thdr)
1079 sip_free_header(thdr);
1080 goto terminate_new_dlg;
1081 }
1082 if (dialog->sip_dlg_type == SIP_UAS_DIALOG) {
1083 dialog->sip_dlg_local_uri_tag = thdr;
1084 } else {
1085 if ((dialog->sip_dlg_remote_uri_tag =
1086 sip_dup_header(thdr)) == NULL) {
1087 (void) pthread_mutex_unlock(
1088 &dialog->sip_dlg_mutex);
1089 goto terminate_new_dlg;
1090 }
1091 }
1092 }
1093
1094 /*
1095 * We take the local contact for UAS Dialog from the response (either
1096 * NOTIFY for SUBSCRIBE request or from final response 2xx to INVITE
1097 * request)
1098 */
1099 if ((dialog->sip_dlg_type == SIP_UAS_DIALOG) && (dialog->sip_dlg_state
1100 == SIP_DLG_CONFIRMED)) {
1101 if (chdr == NULL) {
1102 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
1103 chdr = sip_search_for_header(sip_msg, SIP_CONTACT,
1104 NULL);
1105 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
1106 }
1107 if ((chdr == NULL) || ((dialog->sip_dlg_local_contact =
1108 sip_dup_header(chdr)) == NULL)) {
1109 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1110 if (alloc_thdr)
1111 sip_free_header(thdr);
1112 goto terminate_new_dlg;
1113 }
1114 }
1115
1116 /*
1117 * Cancel the partial dialog timer
1118 */
1119 if (SIP_IS_TIMER_RUNNING(dialog->sip_dlg_timer))
1120 SIP_CANCEL_TIMER(dialog->sip_dlg_timer);
1121
1122 if (dialog->sip_dlg_type == SIP_UAC_DIALOG) {
1123 val = sip_get_header_value(dialog->sip_dlg_local_uri_tag,
1124 &error);
1125 } else {
1126 val = sip_get_header_value(dialog->sip_dlg_remote_uri_tag,
1127 &error);
1128 }
1129 if (val == NULL || error != 0) {
1130 sip_write_to_log((void *)dialog, SIP_DIALOG_LOG |
1131 SIP_ASSERT_ERROR, __FILE__, __LINE__);
1132 }
1133 assert(val != NULL && error == 0);
1134 remtag = sip_get_param_value((sip_header_value_t)val, "tag", &error);
1135
1136 val = sip_get_header_value(dialog->sip_dlg_call_id, &error);
1137 callid = &((sip_hdr_value_t *)val)->str_val;
1138
1139 /*
1140 * Get an ID for this dialog
1141 */
1142 if (dialog->sip_dlg_type == SIP_UAC_DIALOG) {
1143 sip_md5_hash(remtag->sip_str_ptr, remtag->sip_str_len,
1144 ttag->sip_str_ptr, ttag->sip_str_len,
1145 callid->sip_str_ptr, callid->sip_str_len,
1146 NULL, 0, NULL, 0, NULL, 0, (uchar_t *)dialog->sip_dlg_id);
1147 } else {
1148 sip_md5_hash(ttag->sip_str_ptr, ttag->sip_str_len,
1149 remtag->sip_str_ptr, remtag->sip_str_len,
1150 callid->sip_str_ptr, callid->sip_str_len,
1151 NULL, 0, NULL, 0, NULL, 0, (uchar_t *)dialog->sip_dlg_id);
1152 }
1153
1154 SIP_DLG_REFCNT_INCR(dialog);
1155 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1156
1157 /*
1158 * Add it to the hash table
1159 */
1160 if (sip_hash_add(sip_dialog_hash, (void *)dialog,
1161 SIP_DIGEST_TO_HASH(dialog->sip_dlg_id)) != 0) {
1162 terminate_new_dlg:
1163 /*
1164 * So that sip_dialog_delete() does not try to remove
1165 * this from the hash table.
1166 */
1167 (void) pthread_mutex_lock(&dialog->sip_dlg_mutex);
1168 if (dialog->sip_dlg_type == SIP_UAS_DIALOG) {
1169 if (dialog->sip_dlg_local_uri_tag != NULL) {
1170 sip_free_header(dialog->sip_dlg_local_uri_tag);
1171 dialog->sip_dlg_local_uri_tag = NULL;
1172 }
1173 } else {
1174 if (dialog->sip_dlg_remote_uri_tag != NULL) {
1175 sip_free_header(dialog->sip_dlg_remote_uri_tag);
1176 dialog->sip_dlg_remote_uri_tag = NULL;
1177 }
1178 }
1179 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1180 sip_dialog_terminate(dialog, (sip_msg_t)sip_msg);
1181 return (NULL);
1182 }
1183 if (sip_dlg_ulp_state_cb != NULL) {
1184 sip_dlg_ulp_state_cb((sip_dialog_t)dialog,
1185 (sip_msg_t)sip_msg, prev_state, dialog->sip_dlg_state);
1186 }
1187 return ((sip_dialog_t)dialog);
1188 }
1189
1190 /*
1191 * Check if this dialog is a match.
1192 */
1193 boolean_t
sip_dialog_match(void * obj,void * hindex)1194 sip_dialog_match(void *obj, void *hindex)
1195 {
1196 _sip_dialog_t *dialog = (_sip_dialog_t *)obj;
1197
1198 (void) pthread_mutex_lock(&dialog->sip_dlg_mutex);
1199 if (dialog->sip_dlg_state == SIP_DLG_DESTROYED) {
1200 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1201 return (B_FALSE);
1202 }
1203 if (bcmp(dialog->sip_dlg_id, hindex,
1204 sizeof (dialog->sip_dlg_id)) == 0) {
1205 SIP_DLG_REFCNT_INCR(dialog);
1206 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1207 return (B_TRUE);
1208 }
1209 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1210 return (B_FALSE);
1211 }
1212
1213 /*
1214 * Don't delete, just take it out of the hash
1215 */
1216 boolean_t
sip_dialog_dontfree(void * obj,void * hindex,int * found)1217 sip_dialog_dontfree(void *obj, void *hindex, int *found)
1218 {
1219 _sip_dialog_t *dialog = (_sip_dialog_t *)obj;
1220
1221 *found = 0;
1222 (void) pthread_mutex_lock(&dialog->sip_dlg_mutex);
1223 if (bcmp(dialog->sip_dlg_id, hindex, sizeof (dialog->sip_dlg_id))
1224 == 0) {
1225 *found = 1;
1226 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1227 return (B_TRUE);
1228 }
1229 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1230 return (B_FALSE);
1231 }
1232
1233 /*
1234 * Free resources associated with the dialog, the object will be removed
1235 * from the hash list by sip_hash_delete.
1236 */
1237 boolean_t
sip_dialog_free(void * obj,void * hindex,int * found)1238 sip_dialog_free(void *obj, void *hindex, int *found)
1239 {
1240 _sip_dialog_t *dialog = (_sip_dialog_t *)obj;
1241
1242 *found = 0;
1243 (void) pthread_mutex_lock(&dialog->sip_dlg_mutex);
1244 if (bcmp(dialog->sip_dlg_id, hindex, sizeof (dialog->sip_dlg_id))
1245 == 0) {
1246 *found = 1;
1247 if (dialog->sip_dlg_state != SIP_DLG_DESTROYED) {
1248 sip_write_to_log((void *)dialog, SIP_DIALOG_LOG |
1249 SIP_ASSERT_ERROR, __FILE__, __LINE__);
1250 }
1251 assert(dialog->sip_dlg_state == SIP_DLG_DESTROYED);
1252 if (dialog->sip_dlg_ref_cnt != 0) {
1253 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1254 return (B_FALSE);
1255 }
1256 sip_write_to_log((void *)dialog, SIP_DIALOG_LOG, NULL, 0);
1257 sip_release_dialog_res(dialog);
1258 return (B_TRUE);
1259 }
1260 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1261 return (B_FALSE);
1262 }
1263
1264 /*
1265 * The UAS will receive the request from the transaction layer. If the
1266 * request has a tag in the To header field, the UAS core computes the
1267 * dialog identifier corresponding to the request and compares it with
1268 * existing dialogs. If there is a match, this is a mid-dialog request.
1269 */
1270 sip_dialog_t
sip_dialog_find(_sip_msg_t * sip_msg)1271 sip_dialog_find(_sip_msg_t *sip_msg)
1272 {
1273 const sip_str_t *localtag;
1274 const sip_str_t *remtag;
1275 const sip_str_t *callid;
1276 uint16_t digest[8];
1277 _sip_dialog_t *dialog;
1278 boolean_t is_request;
1279 int error;
1280
1281 is_request = sip_msg_is_request((sip_msg_t)sip_msg, &error);
1282 if (error != 0)
1283 return (NULL);
1284 if (is_request) {
1285 localtag = sip_get_to_tag((sip_msg_t)sip_msg, &error);
1286 if (error == 0)
1287 remtag = sip_get_from_tag((sip_msg_t)sip_msg, &error);
1288 } else {
1289 remtag = sip_get_to_tag((sip_msg_t)sip_msg, &error);
1290 if (error == 0)
1291 localtag = sip_get_from_tag((sip_msg_t)sip_msg, &error);
1292 }
1293 if (error != 0)
1294 return (NULL);
1295 callid = sip_get_callid((sip_msg_t)sip_msg, &error);
1296 if (error != 0 || remtag == NULL || localtag == NULL ||
1297 callid == NULL) {
1298 return (NULL);
1299 }
1300 sip_md5_hash(localtag->sip_str_ptr, localtag->sip_str_len,
1301 remtag->sip_str_ptr, remtag->sip_str_len,
1302 callid->sip_str_ptr, callid->sip_str_len,
1303 NULL, 0, NULL, 0, NULL, 0, (uchar_t *)digest);
1304
1305 dialog = (_sip_dialog_t *)sip_hash_find(sip_dialog_hash,
1306 (void *)digest, SIP_DIGEST_TO_HASH(digest), sip_dialog_match);
1307 if (dialog == NULL) {
1308 sip_md5_hash(localtag->sip_str_ptr, localtag->sip_str_len,
1309 NULL, 0, callid->sip_str_ptr, callid->sip_str_len,
1310 NULL, 0, NULL, 0, NULL, 0, (uchar_t *)digest);
1311 dialog = (_sip_dialog_t *)sip_hash_find(sip_dialog_phash,
1312 (void *)digest, SIP_DIGEST_TO_HASH(digest),
1313 sip_dialog_match);
1314 }
1315 return ((sip_dialog_t)dialog);
1316 }
1317
1318 /*
1319 * We keep this partial dialog for the duration of the INVITE
1320 * transaction timeout duration, i.e. Timer B.
1321 */
1322 void
sip_dlg_self_destruct(void * args)1323 sip_dlg_self_destruct(void *args)
1324 {
1325 sip_dialog_timer_obj_t *tim_obj = (sip_dialog_timer_obj_t *)args;
1326 _sip_dialog_t *dialog = (_sip_dialog_t *)tim_obj->dialog;
1327 int index;
1328
1329 (void) pthread_mutex_lock(&dialog->sip_dlg_mutex);
1330 if (dialog->sip_dlg_state != SIP_DLG_NEW) {
1331 sip_write_to_log((void *)dialog, SIP_DIALOG_LOG |
1332 SIP_ASSERT_ERROR, __FILE__, __LINE__);
1333 }
1334 assert(dialog->sip_dlg_state == SIP_DLG_NEW);
1335 dialog->sip_dlg_state = SIP_DLG_DESTROYED;
1336 if (dialog->sip_dlg_type == SIP_UAC_DIALOG) {
1337 index = SIP_DIGEST_TO_HASH(dialog->sip_dlg_id);
1338 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1339 sip_hash_delete(sip_dialog_phash, (void *)dialog->sip_dlg_id,
1340 index, sip_dialog_dontfree);
1341 } else {
1342 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1343 }
1344 if (tim_obj->func != NULL)
1345 tim_obj->func(dialog, NULL, NULL);
1346 free(tim_obj);
1347 SIP_DLG_REFCNT_DECR(dialog);
1348 }
1349
1350 /*
1351 * Terminate a dialog
1352 */
1353 void
sip_dialog_terminate(_sip_dialog_t * dialog,sip_msg_t sip_msg)1354 sip_dialog_terminate(_sip_dialog_t *dialog, sip_msg_t sip_msg)
1355 {
1356 int prev_state;
1357
1358 (void) pthread_mutex_lock(&dialog->sip_dlg_mutex);
1359 prev_state = dialog->sip_dlg_state;
1360 dialog->sip_dlg_state = SIP_DLG_DESTROYED;
1361 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1362 if (sip_dlg_ulp_state_cb != NULL) {
1363 sip_dlg_ulp_state_cb((sip_dialog_t)dialog, sip_msg, prev_state,
1364 dialog->sip_dlg_state);
1365 }
1366 SIP_DLG_REFCNT_DECR(dialog);
1367 }
1368
1369 /*
1370 * Delete a dialog
1371 */
1372 void
sip_dialog_delete(_sip_dialog_t * dialog)1373 sip_dialog_delete(_sip_dialog_t *dialog)
1374 {
1375 int index;
1376
1377 /*
1378 * partial dialog, not in the hash table
1379 */
1380 if (dialog->sip_dlg_local_uri_tag == NULL ||
1381 dialog->sip_dlg_remote_uri_tag == NULL) {
1382 /*
1383 * Cancel the partial dialog timer
1384 */
1385 if (SIP_IS_TIMER_RUNNING(dialog->sip_dlg_timer))
1386 SIP_CANCEL_TIMER(dialog->sip_dlg_timer);
1387 sip_write_to_log((void *)dialog, SIP_DIALOG_LOG, NULL, 0);
1388 sip_release_dialog_res(dialog);
1389 return;
1390 }
1391 index = SIP_DIGEST_TO_HASH(dialog->sip_dlg_id);
1392 sip_hash_delete(sip_dialog_hash, (void *)dialog->sip_dlg_id, index,
1393 sip_dialog_free);
1394 }
1395
1396 /*
1397 * Get the remote target from the CONTACT header from the 200 OK response
1398 */
1399 static boolean_t
sip_get_rtarg(_sip_dialog_t * dialog,_sip_msg_t * sip_msg)1400 sip_get_rtarg(_sip_dialog_t *dialog, _sip_msg_t *sip_msg)
1401 {
1402 sip_header_t chdr;
1403
1404 if (dialog->sip_dlg_remote_target != NULL)
1405 return (B_TRUE);
1406
1407 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
1408 chdr = sip_search_for_header(sip_msg, SIP_CONTACT, NULL);
1409 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
1410 if (chdr == NULL)
1411 return (B_FALSE);
1412 if ((dialog->sip_dlg_remote_target = sip_dup_header(chdr)) == NULL)
1413 return (B_FALSE);
1414
1415 return (B_TRUE);
1416 }
1417
1418 /*
1419 * Process an incoming request/response
1420 */
1421 /* ARGSUSED */
1422 int
sip_dialog_process(_sip_msg_t * sip_msg,sip_dialog_t * sip_dialog)1423 sip_dialog_process(_sip_msg_t *sip_msg, sip_dialog_t *sip_dialog)
1424 {
1425 boolean_t request;
1426 _sip_dialog_t *_dialog;
1427 int error;
1428
1429 _dialog = (_sip_dialog_t *)*sip_dialog;
1430
1431 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
1432 _dialog->sip_dlg_msgcnt++;
1433 sip_add_log(&_dialog->sip_dlg_log[_dialog->sip_dlg_state],
1434 (sip_msg_t)sip_msg, _dialog->sip_dlg_msgcnt, SIP_DIALOG_LOG);
1435 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1436
1437 request = sip_msg_is_request((sip_msg_t)sip_msg, &error);
1438 if (error != 0)
1439 return (EINVAL);
1440 if (request) {
1441 uint32_t cseq;
1442 sip_method_t method;
1443
1444 cseq = sip_get_callseq_num((sip_msg_t)sip_msg, &error);
1445 if (error != 0)
1446 return (EINVAL);
1447 method = sip_get_callseq_method((sip_msg_t)sip_msg, &error);
1448 if (error != 0)
1449 return (EINVAL);
1450 if (sip_get_request_method((sip_msg_t)sip_msg, &error) !=
1451 method) {
1452 return (EINVAL);
1453 }
1454 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
1455 /*
1456 * Requests that do not change in any way the state
1457 * of a dialog may be received within a dialog.
1458 * They are processed as if they had been received
1459 * outside the dialog.
1460 * For dialogs that have been established with an
1461 * INVITE, the only target refresh request defined is
1462 * re-INVITE.
1463 */
1464 if (_dialog->sip_dlg_method == INVITE &&
1465 method == INVITE && _dialog->sip_dlg_remote_cseq != 0 &&
1466 SIP_CSEQ_LT(cseq, _dialog->sip_dlg_remote_cseq)) {
1467 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1468 return (EPROTO);
1469 }
1470 /*
1471 * Target-Refresh request
1472 */
1473 if (_dialog->sip_dlg_method == INVITE && method == INVITE) {
1474 sip_header_t chdr;
1475 sip_header_t nchdr;
1476
1477 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
1478 chdr = sip_search_for_header(sip_msg, SIP_CONTACT,
1479 NULL);
1480 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
1481 if (chdr != NULL &&
1482 (nchdr = sip_dup_header(chdr)) != NULL) {
1483 if (_dialog->sip_dlg_remote_target != NULL) {
1484 sip_free_header(
1485 _dialog->sip_dlg_remote_target);
1486 }
1487 _dialog->sip_dlg_remote_target = nchdr;
1488 }
1489 }
1490 _dialog->sip_dlg_remote_cseq = cseq;
1491 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1492 } else {
1493 int resp_code;
1494 sip_method_t method;
1495 int error;
1496
1497 resp_code = sip_get_response_code((sip_msg_t)sip_msg, &error);
1498 if (error == 0) {
1499 method = sip_get_callseq_method((sip_msg_t)sip_msg,
1500 &error);
1501 }
1502 if (error != 0)
1503 return (error);
1504
1505 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
1506 if (_dialog->sip_dlg_state == SIP_DLG_DESTROYED) {
1507 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1508 return (0);
1509 }
1510 if (_dialog->sip_dlg_state != SIP_DLG_EARLY &&
1511 _dialog->sip_dlg_state != SIP_DLG_CONFIRMED) {
1512 sip_write_to_log((void *)_dialog, SIP_DIALOG_LOG |
1513 SIP_ASSERT_ERROR, __FILE__, __LINE__);
1514 }
1515 assert(_dialog->sip_dlg_state == SIP_DLG_EARLY ||
1516 _dialog->sip_dlg_state == SIP_DLG_CONFIRMED);
1517 /*
1518 * Let the user delete the dialog if it is not a 1XX/2XX resp
1519 * for an early INVITE dialog.
1520 */
1521 if (SIP_OK_RESP(resp_code)) {
1522 if (method == INVITE) {
1523 if (!sip_get_rtarg(_dialog, sip_msg)) {
1524 (void) pthread_mutex_unlock(
1525 &_dialog->sip_dlg_mutex);
1526 if (sip_ulp_dlg_del_cb != NULL) {
1527 sip_ulp_dlg_del_cb(
1528 (sip_dialog_t)_dialog,
1529 (sip_msg_t)sip_msg, NULL);
1530 }
1531 sip_dialog_terminate(_dialog,
1532 (sip_msg_t)sip_msg);
1533 return (0);
1534 }
1535 if (_dialog->sip_dlg_state == SIP_DLG_EARLY) {
1536 _dialog->sip_dlg_state =
1537 SIP_DLG_CONFIRMED;
1538 (void) sip_dlg_recompute_rset(_dialog,
1539 sip_msg, SIP_UAC_DIALOG);
1540 (void) pthread_mutex_unlock(
1541 &_dialog->sip_dlg_mutex);
1542 if (sip_dlg_ulp_state_cb != NULL) {
1543 sip_dlg_ulp_state_cb(
1544 (sip_dialog_t)_dialog,
1545 sip_msg, SIP_DLG_EARLY,
1546 _dialog->sip_dlg_state);
1547 }
1548 return (0);
1549 } else if (_dialog->sip_dlg_new_local_contact
1550 != NULL) {
1551 if (_dialog->sip_dlg_local_contact ==
1552 NULL) {
1553 (void) sip_write_to_log((void *)
1554 _dialog, SIP_DIALOG_LOG |
1555 SIP_ASSERT_ERROR, __FILE__,
1556 __LINE__);
1557 }
1558 assert(_dialog->sip_dlg_local_contact
1559 != NULL);
1560 sip_free_header(_dialog->
1561 sip_dlg_local_contact);
1562 _dialog->sip_dlg_local_contact =
1563 _dialog->sip_dlg_new_local_contact;
1564 _dialog->sip_dlg_new_local_contact =
1565 NULL;
1566 }
1567 }
1568 }
1569 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1570 }
1571 return (0);
1572 }
1573
1574 /*
1575 * Copy partial dialog to create a complete dialog
1576 */
1577 _sip_dialog_t *
sip_copy_partial_dialog(_sip_dialog_t * dialog)1578 sip_copy_partial_dialog(_sip_dialog_t *dialog)
1579 {
1580 _sip_dialog_t *new_dlg;
1581
1582 new_dlg = calloc(1, sizeof (_sip_dialog_t));
1583 if (new_dlg == NULL)
1584 return (NULL);
1585 if (dialog->sip_dlg_req_uri.sip_str_ptr != NULL) {
1586 new_dlg->sip_dlg_req_uri.sip_str_ptr =
1587 malloc(dialog->sip_dlg_req_uri.sip_str_len + 1);
1588 if (new_dlg->sip_dlg_req_uri.sip_str_ptr == NULL) {
1589 free(new_dlg);
1590 return (NULL);
1591 }
1592 (void) strncpy(new_dlg->sip_dlg_req_uri.sip_str_ptr,
1593 dialog->sip_dlg_req_uri.sip_str_ptr,
1594 dialog->sip_dlg_req_uri.sip_str_len);
1595 new_dlg->sip_dlg_req_uri.sip_str_ptr[
1596 dialog->sip_dlg_req_uri.sip_str_len] = '\0';
1597 new_dlg->sip_dlg_req_uri.sip_str_len =
1598 dialog->sip_dlg_req_uri.sip_str_len;
1599 }
1600 if (dialog->sip_dlg_route_set != NULL) {
1601 if (dialog->sip_dlg_rset.sip_str_ptr == NULL) {
1602 sip_write_to_log((void *)dialog, SIP_DIALOG_LOG |
1603 SIP_ASSERT_ERROR, __FILE__, __LINE__);
1604 }
1605 assert(dialog->sip_dlg_rset.sip_str_ptr != NULL);
1606 new_dlg->sip_dlg_rset.sip_str_ptr =
1607 malloc(dialog->sip_dlg_rset.sip_str_len + 1);
1608 if (new_dlg->sip_dlg_rset.sip_str_ptr == NULL) {
1609 if (new_dlg->sip_dlg_req_uri.sip_str_ptr != NULL)
1610 free(new_dlg->sip_dlg_req_uri.sip_str_ptr);
1611 free(new_dlg);
1612 return (NULL);
1613 }
1614 (void) strncpy(new_dlg->sip_dlg_rset.sip_str_ptr,
1615 dialog->sip_dlg_rset.sip_str_ptr,
1616 dialog->sip_dlg_rset.sip_str_len);
1617 new_dlg->sip_dlg_rset.sip_str_ptr[
1618 dialog->sip_dlg_rset.sip_str_len] = '\0';
1619 new_dlg->sip_dlg_rset.sip_str_len =
1620 dialog->sip_dlg_rset.sip_str_len;
1621
1622 new_dlg->sip_dlg_route_set =
1623 sip_dup_header(dialog->sip_dlg_route_set);
1624 if (new_dlg->sip_dlg_route_set == NULL) {
1625 free(new_dlg->sip_dlg_rset.sip_str_ptr);
1626 if (new_dlg->sip_dlg_req_uri.sip_str_ptr != NULL)
1627 free(new_dlg->sip_dlg_req_uri.sip_str_ptr);
1628 free(new_dlg);
1629 return (NULL);
1630 }
1631 }
1632 if ((new_dlg->sip_dlg_local_uri_tag =
1633 sip_dup_header(dialog->sip_dlg_local_uri_tag)) == NULL ||
1634 (new_dlg->sip_dlg_remote_target =
1635 sip_dup_header(dialog->sip_dlg_remote_target)) == NULL ||
1636 (new_dlg->sip_dlg_local_contact =
1637 sip_dup_header(dialog->sip_dlg_local_contact)) == NULL ||
1638 (new_dlg->sip_dlg_call_id =
1639 sip_dup_header(dialog->sip_dlg_call_id)) == NULL) {
1640 sip_release_dialog_res(new_dlg);
1641 return (NULL);
1642 }
1643 if (dialog->sip_dlg_event != NULL) {
1644 new_dlg->sip_dlg_event = sip_dup_header(dialog->sip_dlg_event);
1645 if (new_dlg->sip_dlg_event == NULL) {
1646 sip_release_dialog_res(new_dlg);
1647 return (NULL);
1648 }
1649 }
1650 new_dlg->sip_dlg_local_cseq = dialog->sip_dlg_local_cseq;
1651 new_dlg->sip_dlg_type = dialog->sip_dlg_type;
1652 new_dlg->sip_dlg_on_fork = B_FALSE;
1653 (void) pthread_mutex_init(&new_dlg->sip_dlg_mutex, NULL);
1654
1655 return (new_dlg);
1656 }
1657
1658 /*
1659 * Update the dialog using the response
1660 */
1661 sip_dialog_t
sip_update_dialog(sip_dialog_t dialog,_sip_msg_t * sip_msg)1662 sip_update_dialog(sip_dialog_t dialog, _sip_msg_t *sip_msg)
1663 {
1664 _sip_dialog_t *_dialog;
1665 boolean_t isreq;
1666 sip_method_t method;
1667 int resp_code = 0;
1668 int prev_state;
1669 boolean_t decr_ref = B_FALSE;
1670 int error;
1671
1672 _dialog = (_sip_dialog_t *)dialog;
1673 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
1674 _dialog->sip_dlg_msgcnt++;
1675 sip_add_log(&_dialog->sip_dlg_log[_dialog->sip_dlg_state],
1676 (sip_msg_t)sip_msg, _dialog->sip_dlg_msgcnt, SIP_DIALOG_LOG);
1677 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1678
1679 isreq = sip_msg_is_request((sip_msg_t)sip_msg, &error);
1680 if (error != 0)
1681 return (dialog);
1682 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
1683 if (isreq) {
1684 method = sip_get_request_method((sip_msg_t)sip_msg, &error);
1685 if (error != 0 || _dialog->sip_dlg_method != SUBSCRIBE ||
1686 method != NOTIFY) {
1687 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1688 return (dialog);
1689 }
1690 } else {
1691 resp_code = sip_get_response_code((sip_msg_t)sip_msg, &error);
1692 if (error != 0) {
1693 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1694 return (dialog);
1695 }
1696 method = sip_get_callseq_method((sip_msg_t)sip_msg, &error);
1697 if (error != 0) {
1698 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1699 return (dialog);
1700 }
1701 }
1702 prev_state = _dialog->sip_dlg_state;
1703 if (_dialog->sip_dlg_state == SIP_DLG_CONFIRMED) {
1704 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1705 } else if (_dialog->sip_dlg_state == SIP_DLG_EARLY) {
1706 /*
1707 * Let the user delete the dialog if it is not a 1XX/2XX resp
1708 * for an early dialog.
1709 */
1710 if (isreq) {
1711 sip_write_to_log((void *)_dialog, SIP_DIALOG_LOG |
1712 SIP_ASSERT_ERROR, __FILE__, __LINE__);
1713 }
1714 assert(!isreq);
1715 if (SIP_OK_RESP(resp_code)) {
1716 _dialog->sip_dlg_state = SIP_DLG_CONFIRMED;
1717 /*
1718 * If we recieved provisional response before we would
1719 * not have captured local contact. So store it now.
1720 */
1721 if (_dialog->sip_dlg_type == SIP_UAS_DIALOG && _dialog->
1722 sip_dlg_method == INVITE && method == INVITE) {
1723 sip_header_t chdr;
1724 (void) pthread_mutex_lock(&sip_msg->
1725 sip_msg_mutex);
1726 chdr = sip_search_for_header(sip_msg,
1727 SIP_CONTACT, NULL);
1728 (void) pthread_mutex_unlock(&sip_msg->
1729 sip_msg_mutex);
1730 if (chdr != NULL) {
1731 _dialog->sip_dlg_local_contact
1732 = sip_dup_header(chdr);
1733 _dialog->sip_dlg_new_local_contact =
1734 NULL;
1735 }
1736 }
1737 (void) sip_dlg_recompute_rset(_dialog, sip_msg,
1738 SIP_UAS_DIALOG);
1739 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1740 if (sip_dlg_ulp_state_cb != NULL) {
1741 sip_dlg_ulp_state_cb(dialog, (sip_msg_t)sip_msg,
1742 prev_state, dialog->sip_dlg_state);
1743 }
1744 } else {
1745 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1746 }
1747 } else if (_dialog->sip_dlg_state == SIP_DLG_NEW) {
1748 if (!isreq && _dialog->sip_dlg_method == SUBSCRIBE &&
1749 SIP_PROVISIONAL_RESP(resp_code)) {
1750 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1751 return (dialog);
1752 }
1753 if (_dialog->sip_dlg_type == SIP_UAC_DIALOG) {
1754 _sip_dialog_t *new_dlg;
1755
1756 if (_dialog->sip_dlg_on_fork) {
1757 new_dlg = sip_copy_partial_dialog(_dialog);
1758 if (new_dlg == NULL) {
1759 (void) pthread_mutex_unlock(
1760 &_dialog->sip_dlg_mutex);
1761 return (dialog);
1762 }
1763 /*
1764 * This decr/incr dance is because the caller
1765 * has incremented the ref on the partial
1766 * dialog, we release it here and incr the
1767 * ref on the new dialog which will be
1768 * released by the caller.
1769 */
1770 (void) pthread_mutex_unlock(
1771 &_dialog->sip_dlg_mutex);
1772 SIP_DLG_REFCNT_DECR(_dialog);
1773 _dialog = new_dlg;
1774 (void) pthread_mutex_lock(
1775 &_dialog->sip_dlg_mutex);
1776 SIP_DLG_REFCNT_INCR(_dialog);
1777 } else {
1778 int index;
1779
1780 /*
1781 * take it out of the list so that further
1782 * responses will not result in a dialog.
1783 * We will have an extra refcount when we
1784 * come back from sip_complete_dialog(), i.e.
1785 * one when the partial dialog was created -
1786 * in sip_seed_dialog(), one held by the caller
1787 * and one that will be added by
1788 * sip_complete_dialog(). We need to release
1789 * the one added by the sip_seed_dialog(),
1790 * since the one in sip_complete_dialog()
1791 * is for the same purpose.
1792 */
1793 if (SIP_IS_TIMER_RUNNING(
1794 _dialog->sip_dlg_timer)) {
1795 SIP_CANCEL_TIMER(
1796 _dialog->sip_dlg_timer);
1797 }
1798 index = SIP_DIGEST_TO_HASH(dialog->sip_dlg_id);
1799 (void) pthread_mutex_unlock(
1800 &_dialog->sip_dlg_mutex);
1801 sip_hash_delete(sip_dialog_phash,
1802 (void *)_dialog->sip_dlg_id,
1803 index, sip_dialog_dontfree);
1804 (void) pthread_mutex_lock(
1805 &_dialog->sip_dlg_mutex);
1806 decr_ref = B_TRUE;
1807 }
1808 } else {
1809 decr_ref = B_TRUE;
1810 }
1811 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1812 if ((dialog = sip_complete_dialog(sip_msg, _dialog)) ==
1813 NULL) {
1814 if (_dialog->sip_dlg_type == SIP_UAC_DIALOG && decr_ref)
1815 SIP_DLG_REFCNT_DECR(_dialog);
1816 return (NULL);
1817 }
1818 if (decr_ref)
1819 SIP_DLG_REFCNT_DECR(_dialog);
1820 } else {
1821 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1822 }
1823 return (dialog);
1824 }
1825
1826 /*
1827 * Initialize the hash table
1828 */
1829 void
sip_dialog_init(void (* ulp_dlg_del)(sip_dialog_t,sip_msg_t,void *),void (* ulp_state_cb)(sip_dialog_t,sip_msg_t,int,int))1830 sip_dialog_init(void (*ulp_dlg_del) (sip_dialog_t, sip_msg_t, void *),
1831 void (*ulp_state_cb)(sip_dialog_t, sip_msg_t, int, int))
1832 {
1833 int cnt;
1834
1835 for (cnt = 0; cnt < SIP_HASH_SZ; cnt++) {
1836 sip_dialog_hash[cnt].hash_count = 0;
1837 sip_dialog_hash[cnt].hash_head = NULL;
1838 sip_dialog_hash[cnt].hash_tail = NULL;
1839 (void) pthread_mutex_init(
1840 &sip_dialog_hash[cnt].sip_hash_mutex, NULL);
1841 sip_dialog_phash[cnt].hash_count = 0;
1842 sip_dialog_phash[cnt].hash_head = NULL;
1843 sip_dialog_phash[cnt].hash_tail = NULL;
1844 (void) pthread_mutex_init(
1845 &sip_dialog_phash[cnt].sip_hash_mutex, NULL);
1846 }
1847 if (ulp_dlg_del != NULL)
1848 sip_ulp_dlg_del_cb = ulp_dlg_del;
1849
1850 if (ulp_state_cb != NULL)
1851 sip_dlg_ulp_state_cb = ulp_state_cb;
1852 }
1853
1854 /*
1855 * Copy the new contact header of re-INVITE
1856 */
1857 void
sip_dialog_add_new_contact(sip_dialog_t dialog,_sip_msg_t * sip_msg)1858 sip_dialog_add_new_contact(sip_dialog_t dialog, _sip_msg_t *sip_msg)
1859 {
1860 sip_header_t chdr = NULL;
1861 sip_header_t nhdr = NULL;
1862
1863 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
1864 chdr = sip_search_for_header(sip_msg, SIP_CONTACT, NULL);
1865 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
1866
1867 if (chdr == NULL)
1868 return;
1869
1870 (void) pthread_mutex_lock(&dialog->sip_dlg_mutex);
1871 if (dialog->sip_dlg_method != INVITE || dialog->sip_dlg_state
1872 != SIP_DLG_CONFIRMED) {
1873 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1874 return;
1875 }
1876
1877 if (((nhdr = sip_dup_header(chdr)) != NULL)) {
1878 if (dialog->sip_dlg_new_local_contact != NULL)
1879 sip_free_header(dialog->sip_dlg_new_local_contact);
1880 dialog->sip_dlg_new_local_contact = nhdr;
1881 }
1882 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1883 }
1884
1885 /*
1886 * Given a state, return the string - This is mostly for debug purposes
1887 */
1888 char *
sip_get_dialog_state_str(int state)1889 sip_get_dialog_state_str(int state)
1890 {
1891 switch (state) {
1892 case SIP_DLG_NEW:
1893 return ("SIP_DLG_NEW");
1894 case SIP_DLG_EARLY:
1895 return ("SIP_DLG_EARLY");
1896 case SIP_DLG_CONFIRMED:
1897 return ("SIP_DLG_CONFIRMED");
1898 case SIP_DLG_DESTROYED:
1899 return ("SIP_DLG_DESTROYED");
1900 default:
1901 return ("UNKNOWN");
1902 }
1903 }
1904