xref: /illumos-gate/usr/src/lib/libsip/common/sip_dialog.c (revision 1da57d551424de5a9d469760be7c4b4d4f10a755)
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