1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <assert.h>
30 #include <ctype.h>
31 #include <errno.h>
32 #include <strings.h>
33 #include <pthread.h>
34 #include <sip.h>
35
36 #include "sip_msg.h"
37 #include "sip_miscdefs.h"
38 #include "sip_parse_uri.h"
39 #include "sip_xaction.h"
40
41 #define SIP_BUF_SIZE 128
42
43 /*
44 * Find the header named header, consecutive calls with old_header
45 * passed in will return next header of the same type.
46 * If no name is passed the first header is returned. consectutive calls
47 * with no name but an old header will return the next header.
48 */
49 const struct sip_header *
sip_get_header(sip_msg_t sip_msg,char * header_name,sip_header_t old_header,int * error)50 sip_get_header(sip_msg_t sip_msg, char *header_name, sip_header_t old_header,
51 int *error)
52 {
53 _sip_msg_t *_sip_msg;
54 const struct sip_header *sip_hdr;
55
56 if (error != NULL)
57 *error = 0;
58 if (sip_msg == NULL) {
59 if (error != NULL)
60 *error = EINVAL;
61 return (NULL);
62 }
63 _sip_msg = (_sip_msg_t *)sip_msg;
64 (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
65 sip_hdr = (sip_header_t)sip_search_for_header((_sip_msg_t *)sip_msg,
66 header_name, (_sip_header_t *)old_header);
67 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
68 if (sip_hdr == NULL && error != NULL)
69 *error = EINVAL;
70 return (sip_hdr);
71 }
72
73 /*
74 * Return the request line as a string. Caller releases the returned string.
75 */
76 char *
sip_reqline_to_str(sip_msg_t sip_msg,int * error)77 sip_reqline_to_str(sip_msg_t sip_msg, int *error)
78 {
79 char *reqstr;
80
81 if (error != NULL)
82 *error = 0;
83 if (sip_msg == NULL || !sip_msg_is_request(sip_msg, error)) {
84 if (error != NULL)
85 *error = EINVAL;
86 return (NULL);
87 }
88 reqstr = _sip_startline_to_str((_sip_msg_t *)sip_msg, error);
89 return (reqstr);
90 }
91
92 /*
93 * Return the response line as a string. Caller releases the returned string.
94 */
95 char *
sip_respline_to_str(sip_msg_t sip_msg,int * error)96 sip_respline_to_str(sip_msg_t sip_msg, int *error)
97 {
98 char *respstr;
99
100 if (error != NULL)
101 *error = 0;
102 if (sip_msg == NULL || sip_msg_is_request(sip_msg, error)) {
103 if (error != NULL)
104 *error = EINVAL;
105 return (NULL);
106 }
107 respstr = _sip_startline_to_str((_sip_msg_t *)sip_msg, error);
108 return (respstr);
109 }
110
111 /*
112 * return the first value of the header
113 */
114 const struct sip_value *
sip_get_header_value(const struct sip_header * sip_header,int * error)115 sip_get_header_value(const struct sip_header *sip_header, int *error)
116 {
117 _sip_header_t *_sip_header;
118 sip_parsed_header_t *sip_parsed_header;
119 int ret = 0;
120 const struct sip_value *value;
121
122 if (error != NULL)
123 *error = 0;
124 if (sip_header == NULL) {
125 if (error != NULL)
126 *error = EINVAL;
127 return (NULL);
128 }
129 _sip_header = (_sip_header_t *)sip_header;
130 if (_sip_header->sip_hdr_sipmsg != NULL) {
131 (void) pthread_mutex_lock(
132 &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
133 }
134 if (_sip_header->sip_header_state == SIP_HEADER_DELETED) {
135 if (_sip_header->sip_hdr_sipmsg != NULL) {
136 (void) pthread_mutex_unlock(
137 &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
138 }
139 if (error != NULL)
140 *error = EINVAL;
141 return (NULL);
142 }
143 ret = _sip_header->sip_header_functions->header_parse_func(
144 _sip_header, &sip_parsed_header);
145 if (_sip_header->sip_hdr_sipmsg != NULL) {
146 (void) pthread_mutex_unlock
147 (&_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
148 }
149 if (error != NULL)
150 *error = ret;
151
152 if (ret != 0)
153 return (NULL);
154 value = (sip_header_value_t)sip_parsed_header->value;
155 while (value != NULL && value->value_state == SIP_VALUE_DELETED)
156 value = value->next;
157 if (value != NULL && value->value_state == SIP_VALUE_BAD &&
158 error != NULL) {
159 *error = EPROTO;
160 }
161 return ((sip_header_value_t)value);
162 }
163
164 /*
165 * Return the next value of the header.
166 */
167 const struct sip_value *
sip_get_next_value(sip_header_value_t old_value,int * error)168 sip_get_next_value(sip_header_value_t old_value, int *error)
169 {
170 const struct sip_value *value;
171
172 if (error != NULL)
173 *error = 0;
174 if (old_value == NULL || old_value->next == NULL) {
175 if (error != NULL)
176 *error = EINVAL;
177 return (NULL);
178 }
179 /*
180 * We never free the deleted values so no need to hold a lock.
181 */
182 value = (sip_header_value_t)old_value->next;
183 while (value != NULL && value->value_state == SIP_VALUE_DELETED)
184 value = value->next;
185 if (value != NULL && value->value_state == SIP_VALUE_BAD &&
186 error != NULL) {
187 *error = EPROTO;
188 }
189 return ((sip_header_value_t)value);
190 }
191
192 /*
193 * Given a SIP message, delete the header "header_name".
194 */
195 int
sip_delete_header_by_name(sip_msg_t msg,char * header_name)196 sip_delete_header_by_name(sip_msg_t msg, char *header_name)
197 {
198 _sip_msg_t *_msg = (_sip_msg_t *)msg;
199 sip_header_t sip_hdr;
200 _sip_header_t *_sip_hdr;
201
202 if (_msg == NULL || header_name == NULL)
203 return (EINVAL);
204 (void) pthread_mutex_lock(&_msg->sip_msg_mutex);
205 if (_msg->sip_msg_cannot_be_modified) {
206 (void) pthread_mutex_unlock(&_msg->sip_msg_mutex);
207 return (EPERM);
208 }
209 sip_hdr = (sip_header_t)sip_search_for_header(_msg, header_name, NULL);
210 if (sip_hdr == NULL) {
211 (void) pthread_mutex_unlock(&_msg->sip_msg_mutex);
212 return (EINVAL);
213 }
214 _sip_hdr = (_sip_header_t *)sip_hdr;
215 _sip_hdr->sip_header_state = SIP_HEADER_DELETED;
216 _sip_hdr->sip_hdr_sipmsg->sip_msg_len -= _sip_hdr->sip_hdr_end -
217 _sip_hdr->sip_hdr_start;
218 assert(_sip_hdr->sip_hdr_sipmsg->sip_msg_len >= 0);
219 if (_msg->sip_msg_buf != NULL)
220 _msg->sip_msg_modified = B_TRUE;
221 (void) pthread_mutex_unlock(&_msg->sip_msg_mutex);
222
223 return (0);
224 }
225
226 /*
227 * Mark the header as deleted.
228 */
229 int
sip_delete_header(sip_header_t sip_header)230 sip_delete_header(sip_header_t sip_header)
231 {
232 _sip_header_t *_sip_header;
233
234 if (sip_header == NULL)
235 return (EINVAL);
236 _sip_header = (_sip_header_t *)sip_header;
237 (void) pthread_mutex_lock(&_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
238 if (_sip_header->sip_hdr_sipmsg->sip_msg_cannot_be_modified) {
239 (void) pthread_mutex_unlock
240 (&_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
241 return (EPERM);
242 }
243 if (_sip_header->sip_header_state == SIP_HEADER_DELETED) {
244 (void) pthread_mutex_unlock(
245 &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
246 return (EINVAL);
247 }
248 _sip_header->sip_header_state = SIP_HEADER_DELETED;
249 _sip_header->sip_hdr_sipmsg->sip_msg_len -= _sip_header->sip_hdr_end -
250 _sip_header->sip_hdr_start;
251 assert(_sip_header->sip_hdr_sipmsg->sip_msg_len >= 0);
252 if (_sip_header->sip_hdr_sipmsg->sip_msg_buf != NULL)
253 _sip_header->sip_hdr_sipmsg->sip_msg_modified = B_TRUE;
254 (void) pthread_mutex_unlock
255 (&_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
256 return (0);
257 }
258
259 /*
260 * Mark the value as deleted.
261 */
262 int
sip_delete_value(sip_header_t sip_header,sip_header_value_t sip_header_value)263 sip_delete_value(sip_header_t sip_header, sip_header_value_t sip_header_value)
264 {
265 _sip_header_t *_sip_header;
266 sip_value_t *_sip_header_value;
267 int vlen;
268 char *c;
269
270 if (sip_header == NULL || sip_header_value == NULL)
271 return (EINVAL);
272 _sip_header = (_sip_header_t *)sip_header;
273 (void) pthread_mutex_lock(&_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
274 if (_sip_header->sip_hdr_sipmsg->sip_msg_cannot_be_modified) {
275 (void) pthread_mutex_unlock(&_sip_header->
276 sip_hdr_sipmsg->sip_msg_mutex);
277 return (EPERM);
278 }
279 if (_sip_header->sip_header_state == SIP_HEADER_DELETED) {
280 (void) pthread_mutex_unlock(
281 &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
282 return (EINVAL);
283 }
284 _sip_header_value = (sip_value_t *)sip_header_value;
285 if (_sip_header_value->value_state == SIP_VALUE_DELETED) {
286 (void) pthread_mutex_unlock(
287 &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
288 return (EINVAL);
289 }
290 _sip_header->sip_header_state = SIP_HEADER_DELETED_VAL;
291 _sip_header_value->value_state = SIP_VALUE_DELETED;
292 vlen = _sip_header_value->value_end - _sip_header_value->value_start;
293 if (_sip_header->sip_hdr_parsed->value == _sip_header_value) {
294 c = _sip_header_value->value_start;
295 while (*c-- != SIP_HCOLON)
296 vlen++;
297 } else {
298 c = _sip_header_value->value_start;
299 while (*c-- != SIP_COMMA)
300 vlen++;
301 }
302 if (_sip_header_value->next == NULL) {
303 sip_value_t *value = _sip_header->sip_hdr_parsed->value;
304 boolean_t crlf_present = B_FALSE;
305 char *s;
306
307 while (value != NULL && value != _sip_header_value) {
308 crlf_present = B_FALSE;
309
310 if (value->value_state == SIP_VALUE_DELETED) {
311 value = value->next;
312 continue;
313 }
314 s = value->value_end;
315 while (s != value->value_start) {
316 if (*s == '\r' && strncmp(s, SIP_CRLF,
317 strlen(SIP_CRLF)) == 0) {
318 crlf_present = B_TRUE;
319 break;
320 }
321 s--;
322 }
323 value = value->next;
324 }
325 if (!crlf_present) {
326 c = _sip_header_value->value_end;
327 while (*c-- != '\r')
328 vlen--;
329 assert(vlen > 0);
330 }
331 }
332 _sip_header->sip_hdr_sipmsg->sip_msg_len -= vlen;
333 if (_sip_header->sip_hdr_sipmsg->sip_msg_buf != NULL)
334 _sip_header->sip_hdr_sipmsg->sip_msg_modified = B_TRUE;
335 (void) pthread_mutex_unlock
336 (&_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
337 return (0);
338 }
339
340 /*
341 * Given a param list, check if a param name exists.
342 */
343 boolean_t
sip_is_param_present(const sip_param_t * param_list,char * param_name,int param_len)344 sip_is_param_present(const sip_param_t *param_list, char *param_name,
345 int param_len)
346 {
347 const sip_param_t *param = param_list;
348
349 while (param != NULL) {
350 if (param->param_name.sip_str_len == param_len &&
351 strncasecmp(param->param_name.sip_str_ptr, param_name,
352 param_len) == 0) {
353 return (B_TRUE);
354 }
355 param = param->param_next;
356 }
357 return (B_FALSE);
358 }
359
360
361 /*
362 * Given a value header return the value of the named param.
363 */
364 const sip_str_t *
sip_get_param_value(sip_header_value_t header_value,char * param_name,int * error)365 sip_get_param_value(sip_header_value_t header_value, char *param_name,
366 int *error)
367 {
368 sip_value_t *_sip_header_value;
369 sip_param_t *sip_param;
370
371 if (error != NULL)
372 *error = 0;
373 if (header_value == NULL || param_name == NULL) {
374 if (error != NULL)
375 *error = EINVAL;
376 return (NULL);
377 }
378 _sip_header_value = (sip_value_t *)header_value;
379 if (_sip_header_value->value_state == SIP_VALUE_DELETED) {
380 if (error != NULL)
381 *error = EINVAL;
382 return (NULL);
383 }
384 if (_sip_header_value->param_list == NULL) {
385 if (error != NULL)
386 *error = EINVAL;
387 return (NULL);
388 }
389 sip_param = sip_get_param_from_list(_sip_header_value->param_list,
390 param_name);
391 if (sip_param != NULL)
392 return (&sip_param->param_value);
393 return (NULL);
394 }
395
396 /*
397 * Return the list of params in the header
398 */
399 const sip_param_t *
sip_get_params(sip_header_value_t header_value,int * error)400 sip_get_params(sip_header_value_t header_value, int *error)
401 {
402 sip_value_t *sip_header_value;
403
404 if (error != NULL)
405 *error = 0;
406 if (header_value == NULL) {
407 if (error != NULL)
408 *error = EINVAL;
409 return (NULL);
410 }
411 sip_header_value = (sip_value_t *)header_value;
412 if (sip_header_value->value_state == SIP_VALUE_DELETED) {
413 if (error != NULL)
414 *error = EINVAL;
415 return (NULL);
416 }
417 return (sip_header_value->param_list);
418 }
419
420 /*
421 * Return true if this is a SIP request
422 */
423 boolean_t
sip_msg_is_request(sip_msg_t sip_msg,int * error)424 sip_msg_is_request(sip_msg_t sip_msg, int *error)
425 {
426 _sip_msg_t *_sip_msg;
427 sip_message_type_t *sip_msg_info;
428 boolean_t ret;
429
430 if (error != NULL)
431 *error = 0;
432 if (sip_msg == NULL) {
433 if (error != NULL)
434 *error = EINVAL;
435 return (B_FALSE);
436 }
437 _sip_msg = (_sip_msg_t *)sip_msg;
438 (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
439 if (_sip_msg->sip_msg_req_res == NULL) {
440 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
441 if (error != NULL)
442 *error = EINVAL;
443 return (B_FALSE);
444 }
445 sip_msg_info = _sip_msg->sip_msg_req_res;
446 ret = sip_msg_info->is_request;
447 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
448 return (ret);
449 }
450
451 /*
452 * Return true if this is a SIP response
453 */
454 boolean_t
sip_msg_is_response(sip_msg_t sip_msg,int * error)455 sip_msg_is_response(sip_msg_t sip_msg, int *error)
456 {
457 boolean_t is_resp;
458 _sip_msg_t *_sip_msg;
459 sip_message_type_t *sip_msg_info;
460
461 if (error != NULL)
462 *error = 0;
463 if (sip_msg == NULL) {
464 if (error != NULL)
465 *error = EINVAL;
466 return (B_FALSE);
467 }
468 _sip_msg = (_sip_msg_t *)sip_msg;
469 (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
470 if (_sip_msg->sip_msg_req_res == NULL) {
471 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
472 if (error != NULL)
473 *error = EINVAL;
474 return (B_FALSE);
475 }
476 sip_msg_info = _sip_msg->sip_msg_req_res;
477 is_resp = !sip_msg_info->is_request;
478 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
479 return (is_resp);
480 }
481
482 /*
483 * Return the method in the request line
484 */
485 sip_method_t
sip_get_request_method(sip_msg_t sip_msg,int * error)486 sip_get_request_method(sip_msg_t sip_msg, int *error)
487 {
488 _sip_msg_t *_sip_msg;
489 sip_message_type_t *sip_msg_info;
490 sip_method_t ret = -1;
491
492 if (error != NULL)
493 *error = 0;
494 if (sip_msg == NULL) {
495 if (error != NULL)
496 *error = EINVAL;
497 return (ret);
498 }
499 _sip_msg = (_sip_msg_t *)sip_msg;
500 (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
501 sip_msg_info = _sip_msg->sip_msg_req_res;
502 if (_sip_msg->sip_msg_req_res == NULL) {
503 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
504 if (error != NULL)
505 *error = EINVAL;
506 return (ret);
507 }
508 if (sip_msg_info->is_request)
509 ret = sip_msg_info->sip_req_method;
510 else if (error != NULL)
511 *error = EINVAL;
512 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
513 return (ret);
514 }
515
516 /*
517 * Return the URI from the request line
518 */
519 const sip_str_t *
sip_get_request_uri_str(sip_msg_t sip_msg,int * error)520 sip_get_request_uri_str(sip_msg_t sip_msg, int *error)
521 {
522 _sip_msg_t *_sip_msg;
523 sip_message_type_t *sip_msg_info;
524 sip_str_t *ret = NULL;
525 struct sip_uri *parsed_uri;
526
527 if (error != NULL)
528 *error = 0;
529 if (sip_msg == NULL) {
530 if (error != NULL)
531 *error = EINVAL;
532 return (NULL);
533 }
534 _sip_msg = (_sip_msg_t *)sip_msg;
535 (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
536 if (_sip_msg->sip_msg_req_res == NULL) {
537 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
538 if (error != NULL)
539 *error = EINVAL;
540 return (NULL);
541 }
542 sip_msg_info = _sip_msg->sip_msg_req_res;
543 if (sip_msg_info->is_request)
544 ret = &sip_msg_info->sip_req_uri;
545 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
546
547 /*
548 * If the error is required, check the validity of the URI via
549 * sip_uri_parse().
550 */
551 if (error != NULL) {
552 parsed_uri = sip_parse_uri(ret, error);
553 if (parsed_uri != NULL)
554 sip_free_parsed_uri((sip_uri_t)parsed_uri);
555 }
556 return (ret);
557 }
558
559 /*
560 * Return the response code
561 */
562 int
sip_get_response_code(sip_msg_t sip_msg,int * error)563 sip_get_response_code(sip_msg_t sip_msg, int *error)
564 {
565 _sip_msg_t *_sip_msg;
566 sip_message_type_t *sip_msg_info;
567 int ret = -1;
568
569 if (error != NULL)
570 *error = 0;
571 if (sip_msg == NULL) {
572 if (error != NULL)
573 *error = EINVAL;
574 return (ret);
575 }
576 _sip_msg = (_sip_msg_t *)sip_msg;
577 (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
578 if (_sip_msg->sip_msg_req_res == NULL) {
579 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
580 if (error != NULL)
581 *error = EINVAL;
582 return (ret);
583 }
584 sip_msg_info = _sip_msg->sip_msg_req_res;
585 if (!sip_msg_info->is_request)
586 ret = sip_msg_info->sip_resp_code;
587 else if (error != NULL)
588 *error = EINVAL;
589 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
590 return (ret);
591 }
592
593 /*
594 * Get the response phrase
595 */
596 const sip_str_t *
sip_get_response_phrase(sip_msg_t sip_msg,int * error)597 sip_get_response_phrase(sip_msg_t sip_msg, int *error)
598 {
599 _sip_msg_t *_sip_msg;
600 sip_message_type_t *sip_msg_info;
601 sip_str_t *ret = NULL;
602
603 if (error != NULL)
604 *error = 0;
605 if (sip_msg == NULL) {
606 if (error != NULL)
607 *error = EINVAL;
608 return (ret);
609 }
610 _sip_msg = (_sip_msg_t *)sip_msg;
611 (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
612 if (_sip_msg->sip_msg_req_res == NULL) {
613 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
614 if (error != NULL)
615 *error = EINVAL;
616 return (ret);
617 }
618 sip_msg_info = _sip_msg->sip_msg_req_res;
619 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
620 if (!sip_msg_info->is_request) {
621 if (sip_msg_info->sip_resp_phrase_len == 0)
622 ret = NULL;
623 else
624 ret = &sip_msg_info->sip_resp_phrase;
625 } else if (error != NULL) {
626 *error = EINVAL;
627 }
628 return (ret);
629 }
630
631 /*
632 * Get the SIP version string
633 */
634 const sip_str_t *
sip_get_sip_version(sip_msg_t sip_msg,int * error)635 sip_get_sip_version(sip_msg_t sip_msg, int *error)
636 {
637 _sip_msg_t *_sip_msg;
638 sip_message_type_t *sip_msg_info;
639 sip_str_t *ret = NULL;
640
641 if (error != NULL)
642 *error = 0;
643 if (sip_msg == NULL) {
644 if (error != NULL)
645 *error = EINVAL;
646 return (ret);
647 }
648 _sip_msg = (_sip_msg_t *)sip_msg;
649 (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
650 if (_sip_msg->sip_msg_req_res == NULL) {
651 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
652 if (error != NULL)
653 *error = EINVAL;
654 return (ret);
655 }
656 sip_msg_info = _sip_msg->sip_msg_req_res;
657 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
658 ret = &sip_msg_info->sip_proto_version.version;
659 return (ret);
660 }
661
662 /*
663 * Return the length of the SIP message
664 */
665 int
sip_get_msg_len(sip_msg_t sip_msg,int * error)666 sip_get_msg_len(sip_msg_t sip_msg, int *error)
667 {
668 _sip_msg_t *_sip_msg;
669
670 if (error != NULL)
671 *error = 0;
672 if (sip_msg == NULL) {
673 if (error != NULL)
674 *error = EINVAL;
675 return (-1);
676 }
677 _sip_msg = (_sip_msg_t *)sip_msg;
678
679 return (_sip_msg->sip_msg_len);
680 }
681
682 /*
683 * Get content as a string. Caller frees the string
684 */
685 char *
sip_get_content(sip_msg_t sip_msg,int * error)686 sip_get_content(sip_msg_t sip_msg, int *error)
687 {
688 _sip_msg_t *_sip_msg;
689 sip_content_t *sip_content;
690 char *content;
691 int len;
692 char *p;
693
694 if (error != NULL)
695 *error = 0;
696
697 if (sip_msg == NULL) {
698 if (error != NULL)
699 *error = EINVAL;
700 return (NULL);
701 }
702 _sip_msg = (_sip_msg_t *)sip_msg;
703 (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
704 if (_sip_msg->sip_msg_content == NULL) {
705 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
706 if (error != NULL)
707 *error = EINVAL;
708 return (NULL);
709 }
710 content = malloc(_sip_msg->sip_msg_content_len + 1);
711 if (content == NULL) {
712 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
713 if (error != NULL)
714 *error = ENOMEM;
715 return (NULL);
716 }
717 p = content;
718 sip_content = _sip_msg->sip_msg_content;
719 while (sip_content != NULL) {
720 len = sip_content->sip_content_end -
721 sip_content->sip_content_start;
722 (void) strncpy(p, sip_content->sip_content_start, len);
723 p += len;
724 sip_content = sip_content->sip_content_next;
725 }
726 content[_sip_msg->sip_msg_content_len] = '\0';
727 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
728 return (content);
729 }
730
731 /*
732 * copy sip_header with param, if any, to sip_msg
733 */
734 int
sip_copy_header(sip_msg_t sip_msg,sip_header_t sip_header,char * param)735 sip_copy_header(sip_msg_t sip_msg, sip_header_t sip_header, char *param)
736 {
737 _sip_msg_t *_sip_msg;
738 _sip_header_t *_sip_header;
739 int ret;
740
741 if (sip_msg == NULL || sip_header == NULL)
742 return (EINVAL);
743 _sip_msg = (_sip_msg_t *)sip_msg;
744 _sip_header = (_sip_header_t *)sip_header;
745 (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
746 if (_sip_msg->sip_msg_cannot_be_modified) {
747 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
748 return (EPERM);
749 }
750 if (_sip_header->sip_header_state == SIP_HEADER_DELETED) {
751 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
752 return (EINVAL);
753 }
754
755 ret = _sip_copy_header(_sip_msg, _sip_header, param, B_TRUE);
756 if (_sip_msg->sip_msg_buf != NULL)
757 _sip_msg->sip_msg_modified = B_TRUE;
758 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
759 return (ret);
760 }
761
762 /*
763 * copy the header specified by header_name, with param, if any
764 */
765 int
sip_copy_header_by_name(sip_msg_t old_msg,sip_msg_t new_msg,char * header_name,char * param)766 sip_copy_header_by_name(sip_msg_t old_msg, sip_msg_t new_msg,
767 char *header_name, char *param)
768 {
769 int ret;
770 _sip_msg_t *_old_msg = (_sip_msg_t *)old_msg;
771 _sip_msg_t *_new_msg = (_sip_msg_t *)new_msg;
772
773 if (_old_msg == NULL || _new_msg == NULL || header_name == NULL ||
774 _old_msg == _new_msg) {
775 return (EINVAL);
776 }
777 (void) pthread_mutex_lock(&_new_msg->sip_msg_mutex);
778 if (_new_msg->sip_msg_cannot_be_modified) {
779 (void) pthread_mutex_unlock(&_new_msg->sip_msg_mutex);
780 return (EPERM);
781 }
782
783 (void) pthread_mutex_lock(&_old_msg->sip_msg_mutex);
784 ret = _sip_find_and_copy_header(_old_msg, _new_msg, header_name, param,
785 B_FALSE);
786 (void) pthread_mutex_unlock(&_old_msg->sip_msg_mutex);
787 if (_new_msg->sip_msg_buf != NULL)
788 _new_msg->sip_msg_modified = B_TRUE;
789 (void) pthread_mutex_unlock(&_new_msg->sip_msg_mutex);
790 return (ret);
791 }
792
793 /*
794 * add the given header to sip_message
795 */
796 int
sip_add_header(sip_msg_t sip_msg,char * header_string)797 sip_add_header(sip_msg_t sip_msg, char *header_string)
798 {
799 int header_size;
800 _sip_header_t *new_header;
801 _sip_msg_t *_sip_msg;
802
803 if (sip_msg == NULL || header_string == NULL)
804 return (EINVAL);
805 _sip_msg = (_sip_msg_t *)sip_msg;
806 (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
807 if (_sip_msg->sip_msg_cannot_be_modified) {
808 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
809 return (EPERM);
810 }
811 header_size = strlen(header_string) + strlen(SIP_CRLF);
812 new_header = sip_new_header(header_size);
813 if (new_header == NULL) {
814 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
815 return (ENOMEM);
816 }
817
818 (void) snprintf(new_header->sip_hdr_start, header_size + 1, "%s%s",
819 header_string, SIP_CRLF);
820 _sip_add_header(_sip_msg, new_header, B_TRUE, B_FALSE, NULL);
821 if (_sip_msg->sip_msg_buf != NULL)
822 _sip_msg->sip_msg_modified = B_TRUE;
823 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
824 return (0);
825 }
826
827 /*
828 * add the given param to the sip_header. create a new header with the param
829 * and mark the old header as deleted.
830 */
831 sip_header_t
sip_add_param(sip_header_t sip_header,char * param,int * error)832 sip_add_param(sip_header_t sip_header, char *param, int *error)
833 {
834 _sip_header_t *_sip_header;
835 _sip_header_t *new_header;
836 int hdrlen;
837 _sip_msg_t *_sip_msg;
838 int param_len;
839 char *tmp_ptr;
840
841 if (error != NULL)
842 *error = 0;
843
844 if (param == NULL || sip_header == NULL) {
845 if (error != NULL)
846 *error = EINVAL;
847 return (NULL);
848 }
849
850 _sip_header = (_sip_header_t *)sip_header;
851
852 (void) pthread_mutex_lock(&_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
853 if (_sip_header->sip_hdr_sipmsg->sip_msg_cannot_be_modified) {
854 if (error != NULL)
855 *error = EPERM;
856 (void) pthread_mutex_unlock(
857 &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
858 return (NULL);
859 }
860 if (_sip_header->sip_header_state == SIP_HEADER_DELETED) {
861 if (error != NULL)
862 *error = EINVAL;
863 (void) pthread_mutex_unlock(
864 &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
865 return (NULL);
866 }
867
868 param_len = SIP_SPACE_LEN + sizeof (char) + SIP_SPACE_LEN +
869 strlen(param);
870 hdrlen = _sip_header->sip_hdr_end - _sip_header->sip_hdr_start;
871 new_header = sip_new_header(hdrlen + param_len);
872 if (new_header == NULL) {
873 if (error != NULL)
874 *error = ENOMEM;
875 (void) pthread_mutex_unlock(
876 &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
877 return (NULL);
878 }
879 (void) memcpy(new_header->sip_hdr_start, _sip_header->sip_hdr_start,
880 hdrlen);
881 new_header->sip_hdr_end = new_header->sip_hdr_start + hdrlen;
882 hdrlen = param_len + 1;
883 /*
884 * Find CRLF
885 */
886 tmp_ptr = new_header->sip_hdr_end;
887 while (*tmp_ptr-- != '\n') {
888 hdrlen++;
889 if (tmp_ptr == new_header->sip_hdr_start) {
890 sip_free_header(new_header);
891 if (error != NULL)
892 *error = EINVAL;
893 (void) pthread_mutex_unlock(
894 &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
895 return (NULL);
896 }
897 }
898 (void) snprintf(tmp_ptr, hdrlen + 1,
899 " %c %s%s", SIP_SEMI, param, SIP_CRLF);
900 new_header->sip_hdr_end += param_len;
901 new_header->sip_header_functions = _sip_header->sip_header_functions;
902 _sip_msg = _sip_header->sip_hdr_sipmsg;
903 _sip_add_header(_sip_msg, new_header, B_TRUE, B_FALSE, NULL);
904 if (_sip_header->sip_hdr_sipmsg->sip_msg_buf != NULL)
905 _sip_header->sip_hdr_sipmsg->sip_msg_modified = B_TRUE;
906 (void) pthread_mutex_unlock(&new_header->sip_hdr_sipmsg->sip_msg_mutex);
907 (void) sip_delete_header(sip_header);
908 return ((sip_header_t)new_header);
909 }
910
911 /*
912 * Get Request URI
913 */
914 const struct sip_uri *
sip_get_request_uri(sip_msg_t sip_msg,int * error)915 sip_get_request_uri(sip_msg_t sip_msg, int *error)
916 {
917 _sip_msg_t *_sip_msg;
918 sip_message_type_t *sip_msg_info;
919 const struct sip_uri *ret = NULL;
920
921 if (error != NULL)
922 *error = 0;
923
924 if (sip_msg == NULL) {
925 if (error != NULL)
926 *error = EINVAL;
927 return (NULL);
928 }
929 _sip_msg = (_sip_msg_t *)sip_msg;
930 (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
931 sip_msg_info = _sip_msg->sip_msg_req_res;
932 if (sip_msg_info != NULL && sip_msg_info->is_request) {
933 ret = sip_msg_info->sip_req_parse_uri;
934 } else {
935 if (error != NULL)
936 *error = EINVAL;
937 }
938 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
939
940 if (ret != NULL) {
941 if (ret->sip_uri_scheme.sip_str_len == 0 ||
942 ret->sip_uri_scheme.sip_str_ptr == NULL) {
943 ret = NULL;
944 if (error != NULL)
945 *error = EINVAL;
946 } else if (ret->sip_uri_errflags != 0 && error != NULL) {
947 *error = EINVAL;
948 }
949 }
950 return ((sip_uri_t)ret);
951 }
952
953 /*
954 * returns a comma separated string of all the sent-by values registered by
955 * the UA.
956 */
957 char *
sip_sent_by_to_str(int * error)958 sip_sent_by_to_str(int *error)
959 {
960 sent_by_list_t *sb;
961 int sb_len = 0;
962 int slen;
963 char *sb_str;
964 char *p;
965 int count = 0;
966 int cnt = 0;
967
968 if (error != NULL)
969 *error = 0;
970
971 (void) pthread_mutex_lock(&sip_sent_by_lock);
972 if (sip_sent_by == NULL) {
973 (void) pthread_mutex_unlock(&sip_sent_by_lock);
974 return (NULL);
975 }
976 sb = sip_sent_by;
977 for (cnt = 0; cnt < sip_sent_by_count; cnt++) {
978 sb_len += strlen(sb->sb_val);
979 sb = sb->sb_next;
980 }
981 /*
982 * for the commas
983 */
984 sb_len += sip_sent_by_count - 1;
985 sb_str = malloc(sb_len + 1);
986 if (sb_str == NULL) {
987 if (error != NULL)
988 *error = ENOMEM;
989 (void) pthread_mutex_unlock(&sip_sent_by_lock);
990 return (NULL);
991 }
992 sb = sip_sent_by;
993 p = sb_str;
994 slen = sb_len + 1;
995 for (cnt = 0; cnt < sip_sent_by_count; cnt++) {
996 if (cnt == 0) {
997 count = snprintf(p, slen, "%s", sb->sb_val);
998 } else {
999 count = snprintf(p, slen, "%c%s", SIP_COMMA,
1000 sb->sb_val);
1001 }
1002 p += count;
1003 slen -= count;
1004 sb = sb->sb_next;
1005 }
1006 sb_str[sb_len] = '\0';
1007 (void) pthread_mutex_unlock(&sip_sent_by_lock);
1008 return (sb_str);
1009 }
1010
1011 /*
1012 * A comma separated list of sent-by values.
1013 */
1014 int
sip_register_sent_by(char * val)1015 sip_register_sent_by(char *val)
1016 {
1017 sent_by_list_t *sb = NULL;
1018 sent_by_list_t *sb_tail = NULL;
1019 char *str;
1020 int count = 0;
1021
1022 if (val == NULL)
1023 return (EINVAL);
1024 str = strtok(val, ",");
1025 while (str != NULL) {
1026 int slen;
1027 char *start = str;
1028 char *end = str + strlen(str) - 1;
1029
1030 while (isspace(*start))
1031 start++;
1032 while (isspace(*end))
1033 end--;
1034 if (end <= start)
1035 goto err_ret;
1036 slen = end - start + 1;
1037 sb_tail = (sent_by_list_t *)malloc(sizeof (*sb_tail));
1038 if (sb_tail == NULL)
1039 goto err_ret;
1040 sb_tail->sb_next = sb_tail->sb_prev = NULL;
1041 if ((sb_tail->sb_val = (char *)malloc(slen + 1)) == NULL) {
1042 free(sb_tail);
1043 goto err_ret;
1044 }
1045 (void) strncpy(sb_tail->sb_val, start, slen);
1046 sb_tail->sb_val[slen] = '\0';
1047 if (sb == NULL) {
1048 sb = sb_tail;
1049 } else {
1050 sb_tail->sb_next = sb;
1051 sb->sb_prev = sb_tail;
1052 sb = sb_tail;
1053 }
1054 count++;
1055 str = strtok(NULL, ",");
1056 }
1057 sb_tail = sb;
1058 while (sb_tail->sb_next != NULL)
1059 sb_tail = sb_tail->sb_next;
1060 (void) pthread_mutex_lock(&sip_sent_by_lock);
1061 if (sip_sent_by != NULL) {
1062 sb_tail->sb_next = sip_sent_by;
1063 sip_sent_by->sb_prev = sb_tail;
1064 }
1065 sip_sent_by = sb;
1066 sip_sent_by_count += count;
1067 (void) pthread_mutex_unlock(&sip_sent_by_lock);
1068 return (0);
1069 err_ret:
1070 sb_tail = sb;
1071 for (; count > 0; count--) {
1072 sb = sb_tail->sb_next;
1073 free(sb_tail->sb_val);
1074 sb_tail->sb_next = NULL;
1075 sb_tail->sb_prev = NULL;
1076 free(sb_tail);
1077 sb_tail = sb;
1078 }
1079 return (EINVAL);
1080 }
1081
1082 /*
1083 * Un-register sent-by values; 'val' contains a comma separated list
1084 */
1085 void
sip_unregister_sent_by(char * val)1086 sip_unregister_sent_by(char *val)
1087 {
1088 sent_by_list_t *sb;
1089 char *str;
1090 int count = 0;
1091
1092 (void) pthread_mutex_lock(&sip_sent_by_lock);
1093 str = strtok(val, ",");
1094 while (str != NULL) {
1095 sb = sip_sent_by;
1096 for (count = 0; count < sip_sent_by_count; count++) {
1097 if (strncmp(sb->sb_val, str, strlen(str)) == 0) {
1098 if (sb == sip_sent_by) {
1099 if (sb->sb_next != NULL)
1100 sip_sent_by = sb->sb_next;
1101 else
1102 sip_sent_by = NULL;
1103 } else if (sb->sb_next == NULL) {
1104 sb->sb_prev->sb_next = NULL;
1105 } else {
1106 sb->sb_prev->sb_next = sb->sb_next;
1107 sb->sb_next->sb_prev = sb->sb_prev;
1108 }
1109 sip_sent_by_count--;
1110 sb->sb_next = NULL;
1111 sb->sb_prev = NULL;
1112 free(sb->sb_val);
1113 free(sb);
1114 break;
1115 }
1116 sb = sb->sb_next;
1117 }
1118 str = strtok(NULL, ",");
1119 }
1120 (void) pthread_mutex_unlock(&sip_sent_by_lock);
1121 }
1122
1123 /*
1124 * Un-register all the sent-by values
1125 */
1126 void
sip_unregister_all_sent_by()1127 sip_unregister_all_sent_by()
1128 {
1129 sent_by_list_t *sb;
1130 int count;
1131
1132 (void) pthread_mutex_lock(&sip_sent_by_lock);
1133 sb = sip_sent_by;
1134 for (count = 0; count < sip_sent_by_count; count++) {
1135 sip_sent_by = sb->sb_next;
1136 free(sb->sb_val);
1137 sb->sb_next = NULL;
1138 sb->sb_prev = NULL;
1139 free(sb);
1140 sb = sip_sent_by;
1141 }
1142 sip_sent_by = NULL;
1143 sip_sent_by_count = 0;
1144 (void) pthread_mutex_unlock(&sip_sent_by_lock);
1145 }
1146
1147 /*
1148 * Given a response code, return the corresponding phrase
1149 */
1150 char *
sip_get_resp_desc(int resp_code)1151 sip_get_resp_desc(int resp_code)
1152 {
1153 switch (resp_code) {
1154 case SIP_TRYING:
1155 return ("TRYING");
1156 case SIP_RINGING:
1157 return ("RINGING");
1158 case SIP_CALL_IS_BEING_FORWARDED:
1159 return ("CALL_IS_BEING_FORWARDED");
1160 case SIP_QUEUED:
1161 return ("QUEUED");
1162 case SIP_SESSION_PROGRESS:
1163 return ("SESSION_PROGRESS");
1164 case SIP_OK:
1165 return ("OK");
1166 case SIP_ACCEPTED:
1167 return ("ACCEPTED");
1168 case SIP_MULTIPLE_CHOICES:
1169 return ("MULTIPLE_CHOICES");
1170 case SIP_MOVED_PERMANENTLY:
1171 return ("MOVED_PERMANENTLY");
1172 case SIP_MOVED_TEMPORARILY:
1173 return ("MOVED_TEMPORARILY");
1174 case SIP_USE_PROXY:
1175 return ("USE_PROXY");
1176 case SIP_ALTERNATIVE_SERVICE:
1177 return ("ALTERNATIVE_SERVICE");
1178 case SIP_BAD_REQUEST:
1179 return ("BAD_REQUEST");
1180 case SIP_UNAUTHORIZED:
1181 return ("UNAUTHORIZED");
1182 case SIP_PAYMENT_REQUIRED:
1183 return ("PAYMENT_REQUIRED");
1184 case SIP_FORBIDDEN:
1185 return ("FORBIDDEN");
1186 case SIP_NOT_FOUND:
1187 return ("NOT_FOUND");
1188 case SIP_METHOD_NOT_ALLOWED:
1189 return ("METHOD_NOT_ALLOWED");
1190 case SIP_NOT_ACCEPTABLE:
1191 return ("NOT_ACCEPTABLE");
1192 case SIP_PROXY_AUTH_REQUIRED:
1193 return ("PROXY_AUTH_REQUIRED");
1194 case SIP_REQUEST_TIMEOUT:
1195 return ("REQUEST_TIMEOUT");
1196 case SIP_GONE:
1197 return ("GONE");
1198 case SIP_REQUEST_ENTITY_2_LARGE:
1199 return ("REQUEST_ENTITY_2_LARGE");
1200 case SIP_REQUEST_URI_2_LONG:
1201 return ("REQUEST_URI_2_LONG");
1202 case SIP_UNSUPPORTED_MEDIA_TYPE:
1203 return ("UNSUPPORTED_MEDIA_TYPE");
1204 case SIP_UNSUPPORTED_URI_SCHEME:
1205 return ("UNSUPPORTED_URI_SCHEME");
1206 case SIP_BAD_EXTENSION:
1207 return ("BAD_EXTENSION");
1208 case SIP_EXTENSION_REQUIRED:
1209 return ("EXTENSION_REQUIRED");
1210 case SIP_INTERVAL_2_BRIEF:
1211 return ("INTERVAL_2_BRIEF");
1212 case SIP_TEMPORARILY_UNAVAIL:
1213 return ("TEMPORARILY_UNAVAIL");
1214 case SIP_CALL_NON_EXISTANT:
1215 return ("CALL_NON_EXISTANT");
1216 case SIP_LOOP_DETECTED:
1217 return ("LOOP_DETECTED");
1218 case SIP_TOO_MANY_HOOPS:
1219 return ("TOO_MANY_HOOPS");
1220 case SIP_ADDRESS_INCOMPLETE:
1221 return ("ADDRESS_INCOMPLETE");
1222 case SIP_AMBIGUOUS:
1223 return ("AMBIGUOUS");
1224 case SIP_BUSY_HERE:
1225 return ("BUSY_HERE");
1226 case SIP_REQUEST_TERMINATED:
1227 return ("REQUEST_TERMINATED");
1228 case SIP_NOT_ACCEPTABLE_HERE:
1229 return ("NOT_ACCEPTABLE_HERE");
1230 case SIP_BAD_EVENT:
1231 return ("BAD_EVENT");
1232 case SIP_REQUEST_PENDING:
1233 return ("REQUEST_PENDING");
1234 case SIP_UNDECIPHERABLE:
1235 return ("UNDECIPHERABLE");
1236 case SIP_SERVER_INTERNAL_ERROR:
1237 return ("SERVER_INTERNAL_ERROR");
1238 case SIP_NOT_IMPLEMENTED:
1239 return ("NOT_IMPLEMENTED");
1240 case SIP_BAD_GATEWAY:
1241 return ("BAD_GATEWAY");
1242 case SIP_SERVICE_UNAVAILABLE:
1243 return ("SERVICE_UNAVAILABLE");
1244 case SIP_SERVER_TIMEOUT:
1245 return ("SERVER_TIMEOUT");
1246 case SIP_VERSION_NOT_SUPPORTED:
1247 return ("VERSION_NOT_SUPPORTED");
1248 case SIP_MESSAGE_2_LARGE:
1249 return ("MESSAGE_2_LARGE");
1250 case SIP_BUSY_EVERYWHERE:
1251 return ("BUSY_EVERYWHERE");
1252 case SIP_DECLINE:
1253 return ("DECLINE");
1254 case SIP_DOES_NOT_EXIST_ANYWHERE:
1255 return ("DOES_NOT_EXIST_ANYWHERE");
1256 case SIP_NOT_ACCEPTABLE_ANYWHERE:
1257 return ("NOT_ACCEPTABLE_ANYWHERE");
1258 default:
1259 return ("UNKNOWN");
1260 }
1261 }
1262
1263 /*
1264 * The following three fns initialize and destroy the private library
1265 * data in sip_conn_object_t. The assumption is that the 1st member
1266 * of sip_conn_object_t is reserved for library use. The private data
1267 * is used only for byte-stream protocols such as TCP to accumulate
1268 * a complete SIP message, based on the CONTENT-LENGTH value, before
1269 * processing it.
1270 */
1271 int
sip_init_conn_object(sip_conn_object_t obj)1272 sip_init_conn_object(sip_conn_object_t obj)
1273 {
1274 void **obj_val;
1275 sip_conn_obj_pvt_t *pvt_data;
1276
1277 if (obj == NULL)
1278 return (EINVAL);
1279 pvt_data = malloc(sizeof (sip_conn_obj_pvt_t));
1280 if (pvt_data == NULL)
1281 return (ENOMEM);
1282 pvt_data->sip_conn_obj_cache = NULL;
1283 pvt_data->sip_conn_obj_reass = malloc(sizeof (sip_reass_entry_t));
1284 if (pvt_data->sip_conn_obj_reass == NULL) {
1285 free(pvt_data);
1286 return (ENOMEM);
1287 }
1288 bzero(pvt_data->sip_conn_obj_reass, sizeof (sip_reass_entry_t));
1289 (void) pthread_mutex_init(&pvt_data->sip_conn_obj_reass_lock, NULL);
1290 (void) pthread_mutex_init(&pvt_data->sip_conn_obj_cache_lock, NULL);
1291 sip_refhold_conn(obj);
1292 obj_val = (void *)obj;
1293 *obj_val = (void *)pvt_data;
1294
1295 return (0);
1296 }
1297
1298 /*
1299 * Clear private date, if any
1300 */
1301 void
sip_clear_stale_data(sip_conn_object_t obj)1302 sip_clear_stale_data(sip_conn_object_t obj)
1303 {
1304 void **obj_val;
1305 sip_conn_obj_pvt_t *pvt_data;
1306 sip_reass_entry_t *reass;
1307
1308 if (obj == NULL)
1309 return;
1310 obj_val = (void *)obj;
1311 pvt_data = (sip_conn_obj_pvt_t *)*obj_val;
1312 (void) pthread_mutex_lock(&pvt_data->sip_conn_obj_reass_lock);
1313 reass = pvt_data->sip_conn_obj_reass;
1314 if (reass->sip_reass_msg != NULL) {
1315 assert(reass->sip_reass_msglen > 0);
1316 free(reass->sip_reass_msg);
1317 reass->sip_reass_msglen = 0;
1318 }
1319 assert(reass->sip_reass_msglen == 0);
1320 (void) pthread_mutex_unlock(&pvt_data->sip_conn_obj_reass_lock);
1321 }
1322
1323 /*
1324 * Walk through all the transactions, remove if this obj has been cached
1325 * by any.
1326 */
1327 void
sip_conn_destroyed(sip_conn_object_t obj)1328 sip_conn_destroyed(sip_conn_object_t obj)
1329 {
1330 void **obj_val;
1331 sip_conn_obj_pvt_t *pvt_data;
1332
1333 if (obj == NULL)
1334 return;
1335 obj_val = (void *)obj;
1336 pvt_data = (sip_conn_obj_pvt_t *)*obj_val;
1337
1338 sip_clear_stale_data(obj);
1339 free(pvt_data->sip_conn_obj_reass);
1340 pvt_data->sip_conn_obj_reass = NULL;
1341 (void) pthread_mutex_destroy(&pvt_data->sip_conn_obj_reass_lock);
1342
1343 sip_del_conn_obj_cache(obj, NULL);
1344 (void) pthread_mutex_destroy(&pvt_data->sip_conn_obj_cache_lock);
1345
1346 free(pvt_data);
1347 *obj_val = NULL;
1348 sip_refrele_conn(obj);
1349 }
1350