libc: make stdio_impl.h an internal libc header
[unleashed/tickless.git] / usr / src / lib / libsip / common / sip_ui.c
blob44f04354905af0867488b287d5596a97ed523e8b
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <assert.h>
32 #include <ctype.h>
33 #include <errno.h>
34 #include <strings.h>
35 #include <pthread.h>
36 #include <sip.h>
38 #include "sip_msg.h"
39 #include "sip_miscdefs.h"
40 #include "sip_parse_uri.h"
41 #include "sip_xaction.h"
43 #define SIP_BUF_SIZE 128
46 * Find the header named header, consecutive calls with old_header
47 * passed in will return next header of the same type.
48 * If no name is passed the first header is returned. consectutive calls
49 * with no name but an old header will return the next header.
51 const struct sip_header *
52 sip_get_header(sip_msg_t sip_msg, char *header_name, sip_header_t old_header,
53 int *error)
55 _sip_msg_t *_sip_msg;
56 const struct sip_header *sip_hdr;
58 if (error != NULL)
59 *error = 0;
60 if (sip_msg == NULL) {
61 if (error != NULL)
62 *error = EINVAL;
63 return (NULL);
65 _sip_msg = (_sip_msg_t *)sip_msg;
66 (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
67 sip_hdr = (sip_header_t)sip_search_for_header((_sip_msg_t *)sip_msg,
68 header_name, (_sip_header_t *)old_header);
69 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
70 if (sip_hdr == NULL && error != NULL)
71 *error = EINVAL;
72 return (sip_hdr);
76 * Return the request line as a string. Caller releases the returned string.
78 char *
79 sip_reqline_to_str(sip_msg_t sip_msg, int *error)
81 char *reqstr;
83 if (error != NULL)
84 *error = 0;
85 if (sip_msg == NULL || !sip_msg_is_request(sip_msg, error)) {
86 if (error != NULL)
87 *error = EINVAL;
88 return (NULL);
90 reqstr = _sip_startline_to_str((_sip_msg_t *)sip_msg, error);
91 return (reqstr);
95 * Return the response line as a string. Caller releases the returned string.
97 char *
98 sip_respline_to_str(sip_msg_t sip_msg, int *error)
100 char *respstr;
102 if (error != NULL)
103 *error = 0;
104 if (sip_msg == NULL || sip_msg_is_request(sip_msg, error)) {
105 if (error != NULL)
106 *error = EINVAL;
107 return (NULL);
109 respstr = _sip_startline_to_str((_sip_msg_t *)sip_msg, error);
110 return (respstr);
114 * return the first value of the header
116 const struct sip_value *
117 sip_get_header_value(const struct sip_header *sip_header, int *error)
119 _sip_header_t *_sip_header;
120 sip_parsed_header_t *sip_parsed_header;
121 int ret = 0;
122 const struct sip_value *value;
124 if (error != NULL)
125 *error = 0;
126 if (sip_header == NULL) {
127 if (error != NULL)
128 *error = EINVAL;
129 return (NULL);
131 _sip_header = (_sip_header_t *)sip_header;
132 if (_sip_header->sip_hdr_sipmsg != NULL) {
133 (void) pthread_mutex_lock(
134 &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
136 if (_sip_header->sip_header_state == SIP_HEADER_DELETED) {
137 if (_sip_header->sip_hdr_sipmsg != NULL) {
138 (void) pthread_mutex_unlock(
139 &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
141 if (error != NULL)
142 *error = EINVAL;
143 return (NULL);
145 ret = _sip_header->sip_header_functions->header_parse_func(
146 _sip_header, &sip_parsed_header);
147 if (_sip_header->sip_hdr_sipmsg != NULL) {
148 (void) pthread_mutex_unlock
149 (&_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
151 if (error != NULL)
152 *error = ret;
154 if (ret != 0)
155 return (NULL);
156 value = (sip_header_value_t)sip_parsed_header->value;
157 while (value != NULL && value->value_state == SIP_VALUE_DELETED)
158 value = value->next;
159 if (value != NULL && value->value_state == SIP_VALUE_BAD &&
160 error != NULL) {
161 *error = EPROTO;
163 return ((sip_header_value_t)value);
167 * Return the next value of the header.
169 const struct sip_value *
170 sip_get_next_value(sip_header_value_t old_value, int *error)
172 const struct sip_value *value;
174 if (error != NULL)
175 *error = 0;
176 if (old_value == NULL || old_value->next == NULL) {
177 if (error != NULL)
178 *error = EINVAL;
179 return (NULL);
182 * We never free the deleted values so no need to hold a lock.
184 value = (sip_header_value_t)old_value->next;
185 while (value != NULL && value->value_state == SIP_VALUE_DELETED)
186 value = value->next;
187 if (value != NULL && value->value_state == SIP_VALUE_BAD &&
188 error != NULL) {
189 *error = EPROTO;
191 return ((sip_header_value_t)value);
195 * Given a SIP message, delete the header "header_name".
198 sip_delete_header_by_name(sip_msg_t msg, char *header_name)
200 _sip_msg_t *_msg = (_sip_msg_t *)msg;
201 sip_header_t sip_hdr;
202 _sip_header_t *_sip_hdr;
204 if (_msg == NULL || header_name == NULL)
205 return (EINVAL);
206 (void) pthread_mutex_lock(&_msg->sip_msg_mutex);
207 if (_msg->sip_msg_cannot_be_modified) {
208 (void) pthread_mutex_unlock(&_msg->sip_msg_mutex);
209 return (EPERM);
211 sip_hdr = (sip_header_t)sip_search_for_header(_msg, header_name, NULL);
212 if (sip_hdr == NULL) {
213 (void) pthread_mutex_unlock(&_msg->sip_msg_mutex);
214 return (EINVAL);
216 _sip_hdr = (_sip_header_t *)sip_hdr;
217 _sip_hdr->sip_header_state = SIP_HEADER_DELETED;
218 _sip_hdr->sip_hdr_sipmsg->sip_msg_len -= _sip_hdr->sip_hdr_end -
219 _sip_hdr->sip_hdr_start;
220 assert(_sip_hdr->sip_hdr_sipmsg->sip_msg_len >= 0);
221 if (_msg->sip_msg_buf != NULL)
222 _msg->sip_msg_modified = B_TRUE;
223 (void) pthread_mutex_unlock(&_msg->sip_msg_mutex);
225 return (0);
229 * Mark the header as deleted.
232 sip_delete_header(sip_header_t sip_header)
234 _sip_header_t *_sip_header;
236 if (sip_header == NULL)
237 return (EINVAL);
238 _sip_header = (_sip_header_t *)sip_header;
239 (void) pthread_mutex_lock(&_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
240 if (_sip_header->sip_hdr_sipmsg->sip_msg_cannot_be_modified) {
241 (void) pthread_mutex_unlock
242 (&_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
243 return (EPERM);
245 if (_sip_header->sip_header_state == SIP_HEADER_DELETED) {
246 (void) pthread_mutex_unlock(
247 &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
248 return (EINVAL);
250 _sip_header->sip_header_state = SIP_HEADER_DELETED;
251 _sip_header->sip_hdr_sipmsg->sip_msg_len -= _sip_header->sip_hdr_end -
252 _sip_header->sip_hdr_start;
253 assert(_sip_header->sip_hdr_sipmsg->sip_msg_len >= 0);
254 if (_sip_header->sip_hdr_sipmsg->sip_msg_buf != NULL)
255 _sip_header->sip_hdr_sipmsg->sip_msg_modified = B_TRUE;
256 (void) pthread_mutex_unlock
257 (&_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
258 return (0);
262 * Mark the value as deleted.
265 sip_delete_value(sip_header_t sip_header, sip_header_value_t sip_header_value)
267 _sip_header_t *_sip_header;
268 sip_value_t *_sip_header_value;
269 int vlen;
270 char *c;
272 if (sip_header == NULL || sip_header_value == NULL)
273 return (EINVAL);
274 _sip_header = (_sip_header_t *)sip_header;
275 (void) pthread_mutex_lock(&_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
276 if (_sip_header->sip_hdr_sipmsg->sip_msg_cannot_be_modified) {
277 (void) pthread_mutex_unlock(&_sip_header->
278 sip_hdr_sipmsg->sip_msg_mutex);
279 return (EPERM);
281 if (_sip_header->sip_header_state == SIP_HEADER_DELETED) {
282 (void) pthread_mutex_unlock(
283 &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
284 return (EINVAL);
286 _sip_header_value = (sip_value_t *)sip_header_value;
287 if (_sip_header_value->value_state == SIP_VALUE_DELETED) {
288 (void) pthread_mutex_unlock(
289 &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
290 return (EINVAL);
292 _sip_header->sip_header_state = SIP_HEADER_DELETED_VAL;
293 _sip_header_value->value_state = SIP_VALUE_DELETED;
294 vlen = _sip_header_value->value_end - _sip_header_value->value_start;
295 if (_sip_header->sip_hdr_parsed->value == _sip_header_value) {
296 c = _sip_header_value->value_start;
297 while (*c-- != SIP_HCOLON)
298 vlen++;
299 } else {
300 c = _sip_header_value->value_start;
301 while (*c-- != SIP_COMMA)
302 vlen++;
304 if (_sip_header_value->next == NULL) {
305 sip_value_t *value = _sip_header->sip_hdr_parsed->value;
306 boolean_t crlf_present = B_FALSE;
307 char *s;
309 while (value != NULL && value != _sip_header_value) {
310 crlf_present = B_FALSE;
312 if (value->value_state == SIP_VALUE_DELETED) {
313 value = value->next;
314 continue;
316 s = value->value_end;
317 while (s != value->value_start) {
318 if (*s == '\r' && strncmp(s, SIP_CRLF,
319 strlen(SIP_CRLF)) == 0) {
320 crlf_present = B_TRUE;
321 break;
323 s--;
325 value = value->next;
327 if (!crlf_present) {
328 c = _sip_header_value->value_end;
329 while (*c-- != '\r')
330 vlen--;
331 assert(vlen > 0);
334 _sip_header->sip_hdr_sipmsg->sip_msg_len -= vlen;
335 if (_sip_header->sip_hdr_sipmsg->sip_msg_buf != NULL)
336 _sip_header->sip_hdr_sipmsg->sip_msg_modified = B_TRUE;
337 (void) pthread_mutex_unlock
338 (&_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
339 return (0);
343 * Given a param list, check if a param name exists.
345 boolean_t
346 sip_is_param_present(const sip_param_t *param_list, char *param_name,
347 int param_len)
349 const sip_param_t *param = param_list;
351 while (param != NULL) {
352 if (param->param_name.sip_str_len == param_len &&
353 strncasecmp(param->param_name.sip_str_ptr, param_name,
354 param_len) == 0) {
355 return (B_TRUE);
357 param = param->param_next;
359 return (B_FALSE);
364 * Given a value header return the value of the named param.
366 const sip_str_t *
367 sip_get_param_value(sip_header_value_t header_value, char *param_name,
368 int *error)
370 sip_value_t *_sip_header_value;
371 sip_param_t *sip_param;
373 if (error != NULL)
374 *error = 0;
375 if (header_value == NULL || param_name == NULL) {
376 if (error != NULL)
377 *error = EINVAL;
378 return (NULL);
380 _sip_header_value = (sip_value_t *)header_value;
381 if (_sip_header_value->value_state == SIP_VALUE_DELETED) {
382 if (error != NULL)
383 *error = EINVAL;
384 return (NULL);
386 if (_sip_header_value->param_list == NULL) {
387 if (error != NULL)
388 *error = EINVAL;
389 return (NULL);
391 sip_param = sip_get_param_from_list(_sip_header_value->param_list,
392 param_name);
393 if (sip_param != NULL)
394 return (&sip_param->param_value);
395 return (NULL);
399 * Return the list of params in the header
401 const sip_param_t *
402 sip_get_params(sip_header_value_t header_value, int *error)
404 sip_value_t *sip_header_value;
406 if (error != NULL)
407 *error = 0;
408 if (header_value == NULL) {
409 if (error != NULL)
410 *error = EINVAL;
411 return (NULL);
413 sip_header_value = (sip_value_t *)header_value;
414 if (sip_header_value->value_state == SIP_VALUE_DELETED) {
415 if (error != NULL)
416 *error = EINVAL;
417 return (NULL);
419 return (sip_header_value->param_list);
423 * Return true if this is a SIP request
425 boolean_t
426 sip_msg_is_request(sip_msg_t sip_msg, int *error)
428 _sip_msg_t *_sip_msg;
429 sip_message_type_t *sip_msg_info;
430 boolean_t ret;
432 if (error != NULL)
433 *error = 0;
434 if (sip_msg == NULL) {
435 if (error != NULL)
436 *error = EINVAL;
437 return (B_FALSE);
439 _sip_msg = (_sip_msg_t *)sip_msg;
440 (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
441 if (_sip_msg->sip_msg_req_res == NULL) {
442 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
443 if (error != NULL)
444 *error = EINVAL;
445 return (B_FALSE);
447 sip_msg_info = _sip_msg->sip_msg_req_res;
448 ret = sip_msg_info->is_request;
449 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
450 return (ret);
454 * Return true if this is a SIP response
456 boolean_t
457 sip_msg_is_response(sip_msg_t sip_msg, int *error)
459 boolean_t is_resp;
460 _sip_msg_t *_sip_msg;
461 sip_message_type_t *sip_msg_info;
463 if (error != NULL)
464 *error = 0;
465 if (sip_msg == NULL) {
466 if (error != NULL)
467 *error = EINVAL;
468 return (B_FALSE);
470 _sip_msg = (_sip_msg_t *)sip_msg;
471 (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
472 if (_sip_msg->sip_msg_req_res == NULL) {
473 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
474 if (error != NULL)
475 *error = EINVAL;
476 return (B_FALSE);
478 sip_msg_info = _sip_msg->sip_msg_req_res;
479 is_resp = !sip_msg_info->is_request;
480 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
481 return (is_resp);
485 * Return the method in the request line
487 sip_method_t
488 sip_get_request_method(sip_msg_t sip_msg, int *error)
490 _sip_msg_t *_sip_msg;
491 sip_message_type_t *sip_msg_info;
492 sip_method_t ret = -1;
494 if (error != NULL)
495 *error = 0;
496 if (sip_msg == NULL) {
497 if (error != NULL)
498 *error = EINVAL;
499 return (ret);
501 _sip_msg = (_sip_msg_t *)sip_msg;
502 (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
503 sip_msg_info = _sip_msg->sip_msg_req_res;
504 if (_sip_msg->sip_msg_req_res == NULL) {
505 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
506 if (error != NULL)
507 *error = EINVAL;
508 return (ret);
510 if (sip_msg_info->is_request)
511 ret = sip_msg_info->sip_req_method;
512 else if (error != NULL)
513 *error = EINVAL;
514 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
515 return (ret);
519 * Return the URI from the request line
521 const sip_str_t *
522 sip_get_request_uri_str(sip_msg_t sip_msg, int *error)
524 _sip_msg_t *_sip_msg;
525 sip_message_type_t *sip_msg_info;
526 sip_str_t *ret = NULL;
527 struct sip_uri *parsed_uri;
529 if (error != NULL)
530 *error = 0;
531 if (sip_msg == NULL) {
532 if (error != NULL)
533 *error = EINVAL;
534 return (NULL);
536 _sip_msg = (_sip_msg_t *)sip_msg;
537 (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
538 if (_sip_msg->sip_msg_req_res == NULL) {
539 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
540 if (error != NULL)
541 *error = EINVAL;
542 return (NULL);
544 sip_msg_info = _sip_msg->sip_msg_req_res;
545 if (sip_msg_info->is_request)
546 ret = &sip_msg_info->sip_req_uri;
547 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
550 * If the error is required, check the validity of the URI via
551 * sip_uri_parse().
553 if (error != NULL) {
554 parsed_uri = sip_parse_uri(ret, error);
555 if (parsed_uri != NULL)
556 sip_free_parsed_uri((sip_uri_t)parsed_uri);
558 return (ret);
562 * Return the response code
565 sip_get_response_code(sip_msg_t sip_msg, int *error)
567 _sip_msg_t *_sip_msg;
568 sip_message_type_t *sip_msg_info;
569 int ret = -1;
571 if (error != NULL)
572 *error = 0;
573 if (sip_msg == NULL) {
574 if (error != NULL)
575 *error = EINVAL;
576 return (ret);
578 _sip_msg = (_sip_msg_t *)sip_msg;
579 (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
580 if (_sip_msg->sip_msg_req_res == NULL) {
581 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
582 if (error != NULL)
583 *error = EINVAL;
584 return (ret);
586 sip_msg_info = _sip_msg->sip_msg_req_res;
587 if (!sip_msg_info->is_request)
588 ret = sip_msg_info->sip_resp_code;
589 else if (error != NULL)
590 *error = EINVAL;
591 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
592 return (ret);
596 * Get the response phrase
598 const sip_str_t *
599 sip_get_response_phrase(sip_msg_t sip_msg, int *error)
601 _sip_msg_t *_sip_msg;
602 sip_message_type_t *sip_msg_info;
603 sip_str_t *ret = NULL;
605 if (error != NULL)
606 *error = 0;
607 if (sip_msg == NULL) {
608 if (error != NULL)
609 *error = EINVAL;
610 return (ret);
612 _sip_msg = (_sip_msg_t *)sip_msg;
613 (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
614 if (_sip_msg->sip_msg_req_res == NULL) {
615 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
616 if (error != NULL)
617 *error = EINVAL;
618 return (ret);
620 sip_msg_info = _sip_msg->sip_msg_req_res;
621 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
622 if (!sip_msg_info->is_request) {
623 if (sip_msg_info->sip_resp_phrase_len == 0)
624 ret = NULL;
625 else
626 ret = &sip_msg_info->sip_resp_phrase;
627 } else if (error != NULL) {
628 *error = EINVAL;
630 return (ret);
634 * Get the SIP version string
636 const sip_str_t *
637 sip_get_sip_version(sip_msg_t sip_msg, int *error)
639 _sip_msg_t *_sip_msg;
640 sip_message_type_t *sip_msg_info;
641 sip_str_t *ret = NULL;
643 if (error != NULL)
644 *error = 0;
645 if (sip_msg == NULL) {
646 if (error != NULL)
647 *error = EINVAL;
648 return (ret);
650 _sip_msg = (_sip_msg_t *)sip_msg;
651 (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
652 if (_sip_msg->sip_msg_req_res == NULL) {
653 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
654 if (error != NULL)
655 *error = EINVAL;
656 return (ret);
658 sip_msg_info = _sip_msg->sip_msg_req_res;
659 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
660 ret = &sip_msg_info->sip_proto_version.version;
661 return (ret);
665 * Return the length of the SIP message
668 sip_get_msg_len(sip_msg_t sip_msg, int *error)
670 _sip_msg_t *_sip_msg;
672 if (error != NULL)
673 *error = 0;
674 if (sip_msg == NULL) {
675 if (error != NULL)
676 *error = EINVAL;
677 return (-1);
679 _sip_msg = (_sip_msg_t *)sip_msg;
681 return (_sip_msg->sip_msg_len);
685 * Get content as a string. Caller frees the string
687 char *
688 sip_get_content(sip_msg_t sip_msg, int *error)
690 _sip_msg_t *_sip_msg;
691 sip_content_t *sip_content;
692 char *content;
693 int len;
694 char *p;
696 if (error != NULL)
697 *error = 0;
699 if (sip_msg == NULL) {
700 if (error != NULL)
701 *error = EINVAL;
702 return (NULL);
704 _sip_msg = (_sip_msg_t *)sip_msg;
705 (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
706 if (_sip_msg->sip_msg_content == NULL) {
707 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
708 if (error != NULL)
709 *error = EINVAL;
710 return (NULL);
712 content = malloc(_sip_msg->sip_msg_content_len + 1);
713 if (content == NULL) {
714 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
715 if (error != NULL)
716 *error = ENOMEM;
717 return (NULL);
719 p = content;
720 sip_content = _sip_msg->sip_msg_content;
721 while (sip_content != NULL) {
722 len = sip_content->sip_content_end -
723 sip_content->sip_content_start;
724 (void) strncpy(p, sip_content->sip_content_start, len);
725 p += len;
726 sip_content = sip_content->sip_content_next;
728 content[_sip_msg->sip_msg_content_len] = '\0';
729 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
730 return (content);
734 * copy sip_header with param, if any, to sip_msg
737 sip_copy_header(sip_msg_t sip_msg, sip_header_t sip_header, char *param)
739 _sip_msg_t *_sip_msg;
740 _sip_header_t *_sip_header;
741 int ret;
743 if (sip_msg == NULL || sip_header == NULL)
744 return (EINVAL);
745 _sip_msg = (_sip_msg_t *)sip_msg;
746 _sip_header = (_sip_header_t *)sip_header;
747 (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
748 if (_sip_msg->sip_msg_cannot_be_modified) {
749 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
750 return (EPERM);
752 if (_sip_header->sip_header_state == SIP_HEADER_DELETED) {
753 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
754 return (EINVAL);
757 ret = _sip_copy_header(_sip_msg, _sip_header, param, B_TRUE);
758 if (_sip_msg->sip_msg_buf != NULL)
759 _sip_msg->sip_msg_modified = B_TRUE;
760 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
761 return (ret);
765 * copy the header specified by header_name, with param, if any
768 sip_copy_header_by_name(sip_msg_t old_msg, sip_msg_t new_msg,
769 char *header_name, char *param)
771 int ret;
772 _sip_msg_t *_old_msg = (_sip_msg_t *)old_msg;
773 _sip_msg_t *_new_msg = (_sip_msg_t *)new_msg;
775 if (_old_msg == NULL || _new_msg == NULL || header_name == NULL ||
776 _old_msg == _new_msg) {
777 return (EINVAL);
779 (void) pthread_mutex_lock(&_new_msg->sip_msg_mutex);
780 if (_new_msg->sip_msg_cannot_be_modified) {
781 (void) pthread_mutex_unlock(&_new_msg->sip_msg_mutex);
782 return (EPERM);
785 (void) pthread_mutex_lock(&_old_msg->sip_msg_mutex);
786 ret = _sip_find_and_copy_header(_old_msg, _new_msg, header_name, param,
787 B_FALSE);
788 (void) pthread_mutex_unlock(&_old_msg->sip_msg_mutex);
789 if (_new_msg->sip_msg_buf != NULL)
790 _new_msg->sip_msg_modified = B_TRUE;
791 (void) pthread_mutex_unlock(&_new_msg->sip_msg_mutex);
792 return (ret);
796 * add the given header to sip_message
799 sip_add_header(sip_msg_t sip_msg, char *header_string)
801 int header_size;
802 _sip_header_t *new_header;
803 _sip_msg_t *_sip_msg;
805 if (sip_msg == NULL || header_string == NULL)
806 return (EINVAL);
807 _sip_msg = (_sip_msg_t *)sip_msg;
808 (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
809 if (_sip_msg->sip_msg_cannot_be_modified) {
810 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
811 return (EPERM);
813 header_size = strlen(header_string) + strlen(SIP_CRLF);
814 new_header = sip_new_header(header_size);
815 if (new_header == NULL) {
816 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
817 return (ENOMEM);
820 (void) snprintf(new_header->sip_hdr_start, header_size + 1, "%s%s",
821 header_string, SIP_CRLF);
822 _sip_add_header(_sip_msg, new_header, B_TRUE, B_FALSE, NULL);
823 if (_sip_msg->sip_msg_buf != NULL)
824 _sip_msg->sip_msg_modified = B_TRUE;
825 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
826 return (0);
830 * add the given param to the sip_header. create a new header with the param
831 * and mark the old header as deleted.
833 sip_header_t
834 sip_add_param(sip_header_t sip_header, char *param, int *error)
836 _sip_header_t *_sip_header;
837 _sip_header_t *new_header;
838 int hdrlen;
839 _sip_msg_t *_sip_msg;
840 int param_len;
841 char *tmp_ptr;
843 if (error != NULL)
844 *error = 0;
846 if (param == NULL || sip_header == NULL) {
847 if (error != NULL)
848 *error = EINVAL;
849 return (NULL);
852 _sip_header = (_sip_header_t *)sip_header;
854 (void) pthread_mutex_lock(&_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
855 if (_sip_header->sip_hdr_sipmsg->sip_msg_cannot_be_modified) {
856 if (error != NULL)
857 *error = EPERM;
858 (void) pthread_mutex_unlock(
859 &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
860 return (NULL);
862 if (_sip_header->sip_header_state == SIP_HEADER_DELETED) {
863 if (error != NULL)
864 *error = EINVAL;
865 (void) pthread_mutex_unlock(
866 &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
867 return (NULL);
870 param_len = SIP_SPACE_LEN + sizeof (char) + SIP_SPACE_LEN +
871 strlen(param);
872 hdrlen = _sip_header->sip_hdr_end - _sip_header->sip_hdr_start;
873 new_header = sip_new_header(hdrlen + param_len);
874 if (new_header == NULL) {
875 if (error != NULL)
876 *error = ENOMEM;
877 (void) pthread_mutex_unlock(
878 &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
879 return (NULL);
881 (void) memcpy(new_header->sip_hdr_start, _sip_header->sip_hdr_start,
882 hdrlen);
883 new_header->sip_hdr_end = new_header->sip_hdr_start + hdrlen;
884 hdrlen = param_len + 1;
886 * Find CRLF
888 tmp_ptr = new_header->sip_hdr_end;
889 while (*tmp_ptr-- != '\n') {
890 hdrlen++;
891 if (tmp_ptr == new_header->sip_hdr_start) {
892 sip_free_header(new_header);
893 if (error != NULL)
894 *error = EINVAL;
895 (void) pthread_mutex_unlock(
896 &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
897 return (NULL);
900 (void) snprintf(tmp_ptr, hdrlen + 1,
901 " %c %s%s", SIP_SEMI, param, SIP_CRLF);
902 new_header->sip_hdr_end += param_len;
903 new_header->sip_header_functions = _sip_header->sip_header_functions;
904 _sip_msg = _sip_header->sip_hdr_sipmsg;
905 _sip_add_header(_sip_msg, new_header, B_TRUE, B_FALSE, NULL);
906 if (_sip_header->sip_hdr_sipmsg->sip_msg_buf != NULL)
907 _sip_header->sip_hdr_sipmsg->sip_msg_modified = B_TRUE;
908 (void) pthread_mutex_unlock(&new_header->sip_hdr_sipmsg->sip_msg_mutex);
909 (void) sip_delete_header(sip_header);
910 return ((sip_header_t)new_header);
914 * Get Request URI
916 const struct sip_uri *
917 sip_get_request_uri(sip_msg_t sip_msg, int *error)
919 _sip_msg_t *_sip_msg;
920 sip_message_type_t *sip_msg_info;
921 const struct sip_uri *ret = NULL;
923 if (error != NULL)
924 *error = 0;
926 if (sip_msg == NULL) {
927 if (error != NULL)
928 *error = EINVAL;
929 return (NULL);
931 _sip_msg = (_sip_msg_t *)sip_msg;
932 (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
933 sip_msg_info = _sip_msg->sip_msg_req_res;
934 if (sip_msg_info != NULL && sip_msg_info->is_request) {
935 ret = sip_msg_info->sip_req_parse_uri;
936 } else {
937 if (error != NULL)
938 *error = EINVAL;
940 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
942 if (ret != NULL) {
943 if (ret->sip_uri_scheme.sip_str_len == 0 ||
944 ret->sip_uri_scheme.sip_str_ptr == NULL) {
945 ret = NULL;
946 if (error != NULL)
947 *error = EINVAL;
948 } else if (ret->sip_uri_errflags != 0 && error != NULL) {
949 *error = EINVAL;
952 return ((sip_uri_t)ret);
956 * returns a comma separated string of all the sent-by values registered by
957 * the UA.
959 char *
960 sip_sent_by_to_str(int *error)
962 sent_by_list_t *sb;
963 int sb_len = 0;
964 int slen;
965 char *sb_str;
966 char *p;
967 int count = 0;
968 int cnt = 0;
970 if (error != NULL)
971 *error = 0;
973 (void) pthread_mutex_lock(&sip_sent_by_lock);
974 if (sip_sent_by == NULL) {
975 (void) pthread_mutex_unlock(&sip_sent_by_lock);
976 return (NULL);
978 sb = sip_sent_by;
979 for (cnt = 0; cnt < sip_sent_by_count; cnt++) {
980 sb_len += strlen(sb->sb_val);
981 sb = sb->sb_next;
984 * for the commas
986 sb_len += sip_sent_by_count - 1;
987 sb_str = malloc(sb_len + 1);
988 if (sb_str == NULL) {
989 if (error != NULL)
990 *error = ENOMEM;
991 (void) pthread_mutex_unlock(&sip_sent_by_lock);
992 return (NULL);
994 sb = sip_sent_by;
995 p = sb_str;
996 slen = sb_len + 1;
997 for (cnt = 0; cnt < sip_sent_by_count; cnt++) {
998 if (cnt == 0) {
999 count = snprintf(p, slen, "%s", sb->sb_val);
1000 } else {
1001 count = snprintf(p, slen, "%c%s", SIP_COMMA,
1002 sb->sb_val);
1004 p += count;
1005 slen -= count;
1006 sb = sb->sb_next;
1008 sb_str[sb_len] = '\0';
1009 (void) pthread_mutex_unlock(&sip_sent_by_lock);
1010 return (sb_str);
1014 * A comma separated list of sent-by values.
1017 sip_register_sent_by(char *val)
1019 sent_by_list_t *sb = NULL;
1020 sent_by_list_t *sb_tail = NULL;
1021 char *str;
1022 int count = 0;
1024 if (val == NULL)
1025 return (EINVAL);
1026 str = strtok(val, ",");
1027 while (str != NULL) {
1028 int slen;
1029 char *start = str;
1030 char *end = str + strlen(str) - 1;
1032 while (isspace(*start))
1033 start++;
1034 while (isspace(*end))
1035 end--;
1036 if (end <= start)
1037 goto err_ret;
1038 slen = end - start + 1;
1039 sb_tail = (sent_by_list_t *)malloc(sizeof (*sb_tail));
1040 if (sb_tail == NULL)
1041 goto err_ret;
1042 sb_tail->sb_next = sb_tail->sb_prev = NULL;
1043 if ((sb_tail->sb_val = (char *)malloc(slen + 1)) == NULL) {
1044 free(sb_tail);
1045 goto err_ret;
1047 (void) strncpy(sb_tail->sb_val, start, slen);
1048 sb_tail->sb_val[slen] = '\0';
1049 if (sb == NULL) {
1050 sb = sb_tail;
1051 } else {
1052 sb_tail->sb_next = sb;
1053 sb->sb_prev = sb_tail;
1054 sb = sb_tail;
1056 count++;
1057 str = strtok(NULL, ",");
1059 sb_tail = sb;
1060 while (sb_tail->sb_next != NULL)
1061 sb_tail = sb_tail->sb_next;
1062 (void) pthread_mutex_lock(&sip_sent_by_lock);
1063 if (sip_sent_by != NULL) {
1064 sb_tail->sb_next = sip_sent_by;
1065 sip_sent_by->sb_prev = sb_tail;
1067 sip_sent_by = sb;
1068 sip_sent_by_count += count;
1069 (void) pthread_mutex_unlock(&sip_sent_by_lock);
1070 return (0);
1071 err_ret:
1072 sb_tail = sb;
1073 for (; count > 0; count--) {
1074 sb = sb_tail->sb_next;
1075 free(sb_tail->sb_val);
1076 sb_tail->sb_next = NULL;
1077 sb_tail->sb_prev = NULL;
1078 free(sb_tail);
1079 sb_tail = sb;
1081 return (EINVAL);
1085 * Un-register sent-by values; 'val' contains a comma separated list
1087 void
1088 sip_unregister_sent_by(char *val)
1090 sent_by_list_t *sb;
1091 char *str;
1092 int count = 0;
1094 (void) pthread_mutex_lock(&sip_sent_by_lock);
1095 str = strtok(val, ",");
1096 while (str != NULL) {
1097 sb = sip_sent_by;
1098 for (count = 0; count < sip_sent_by_count; count++) {
1099 if (strncmp(sb->sb_val, str, strlen(str)) == 0) {
1100 if (sb == sip_sent_by) {
1101 if (sb->sb_next != NULL)
1102 sip_sent_by = sb->sb_next;
1103 else
1104 sip_sent_by = NULL;
1105 } else if (sb->sb_next == NULL) {
1106 sb->sb_prev->sb_next = NULL;
1107 } else {
1108 sb->sb_prev->sb_next = sb->sb_next;
1109 sb->sb_next->sb_prev = sb->sb_prev;
1111 sip_sent_by_count--;
1112 sb->sb_next = NULL;
1113 sb->sb_prev = NULL;
1114 free(sb->sb_val);
1115 free(sb);
1116 break;
1118 sb = sb->sb_next;
1120 str = strtok(NULL, ",");
1122 (void) pthread_mutex_unlock(&sip_sent_by_lock);
1126 * Un-register all the sent-by values
1128 void
1129 sip_unregister_all_sent_by()
1131 sent_by_list_t *sb;
1132 int count;
1134 (void) pthread_mutex_lock(&sip_sent_by_lock);
1135 sb = sip_sent_by;
1136 for (count = 0; count < sip_sent_by_count; count++) {
1137 sip_sent_by = sb->sb_next;
1138 free(sb->sb_val);
1139 sb->sb_next = NULL;
1140 sb->sb_prev = NULL;
1141 free(sb);
1142 sb = sip_sent_by;
1144 sip_sent_by = NULL;
1145 sip_sent_by_count = 0;
1146 (void) pthread_mutex_unlock(&sip_sent_by_lock);
1150 * Given a response code, return the corresponding phrase
1152 char *
1153 sip_get_resp_desc(int resp_code)
1155 switch (resp_code) {
1156 case SIP_TRYING:
1157 return ("TRYING");
1158 case SIP_RINGING:
1159 return ("RINGING");
1160 case SIP_CALL_IS_BEING_FORWARDED:
1161 return ("CALL_IS_BEING_FORWARDED");
1162 case SIP_QUEUED:
1163 return ("QUEUED");
1164 case SIP_SESSION_PROGRESS:
1165 return ("SESSION_PROGRESS");
1166 case SIP_OK:
1167 return ("OK");
1168 case SIP_ACCEPTED:
1169 return ("ACCEPTED");
1170 case SIP_MULTIPLE_CHOICES:
1171 return ("MULTIPLE_CHOICES");
1172 case SIP_MOVED_PERMANENTLY:
1173 return ("MOVED_PERMANENTLY");
1174 case SIP_MOVED_TEMPORARILY:
1175 return ("MOVED_TEMPORARILY");
1176 case SIP_USE_PROXY:
1177 return ("USE_PROXY");
1178 case SIP_ALTERNATIVE_SERVICE:
1179 return ("ALTERNATIVE_SERVICE");
1180 case SIP_BAD_REQUEST:
1181 return ("BAD_REQUEST");
1182 case SIP_UNAUTHORIZED:
1183 return ("UNAUTHORIZED");
1184 case SIP_PAYMENT_REQUIRED:
1185 return ("PAYMENT_REQUIRED");
1186 case SIP_FORBIDDEN:
1187 return ("FORBIDDEN");
1188 case SIP_NOT_FOUND:
1189 return ("NOT_FOUND");
1190 case SIP_METHOD_NOT_ALLOWED:
1191 return ("METHOD_NOT_ALLOWED");
1192 case SIP_NOT_ACCEPTABLE:
1193 return ("NOT_ACCEPTABLE");
1194 case SIP_PROXY_AUTH_REQUIRED:
1195 return ("PROXY_AUTH_REQUIRED");
1196 case SIP_REQUEST_TIMEOUT:
1197 return ("REQUEST_TIMEOUT");
1198 case SIP_GONE:
1199 return ("GONE");
1200 case SIP_REQUEST_ENTITY_2_LARGE:
1201 return ("REQUEST_ENTITY_2_LARGE");
1202 case SIP_REQUEST_URI_2_LONG:
1203 return ("REQUEST_URI_2_LONG");
1204 case SIP_UNSUPPORTED_MEDIA_TYPE:
1205 return ("UNSUPPORTED_MEDIA_TYPE");
1206 case SIP_UNSUPPORTED_URI_SCHEME:
1207 return ("UNSUPPORTED_URI_SCHEME");
1208 case SIP_BAD_EXTENSION:
1209 return ("BAD_EXTENSION");
1210 case SIP_EXTENSION_REQUIRED:
1211 return ("EXTENSION_REQUIRED");
1212 case SIP_INTERVAL_2_BRIEF:
1213 return ("INTERVAL_2_BRIEF");
1214 case SIP_TEMPORARILY_UNAVAIL:
1215 return ("TEMPORARILY_UNAVAIL");
1216 case SIP_CALL_NON_EXISTANT:
1217 return ("CALL_NON_EXISTANT");
1218 case SIP_LOOP_DETECTED:
1219 return ("LOOP_DETECTED");
1220 case SIP_TOO_MANY_HOOPS:
1221 return ("TOO_MANY_HOOPS");
1222 case SIP_ADDRESS_INCOMPLETE:
1223 return ("ADDRESS_INCOMPLETE");
1224 case SIP_AMBIGUOUS:
1225 return ("AMBIGUOUS");
1226 case SIP_BUSY_HERE:
1227 return ("BUSY_HERE");
1228 case SIP_REQUEST_TERMINATED:
1229 return ("REQUEST_TERMINATED");
1230 case SIP_NOT_ACCEPTABLE_HERE:
1231 return ("NOT_ACCEPTABLE_HERE");
1232 case SIP_BAD_EVENT:
1233 return ("BAD_EVENT");
1234 case SIP_REQUEST_PENDING:
1235 return ("REQUEST_PENDING");
1236 case SIP_UNDECIPHERABLE:
1237 return ("UNDECIPHERABLE");
1238 case SIP_SERVER_INTERNAL_ERROR:
1239 return ("SERVER_INTERNAL_ERROR");
1240 case SIP_NOT_IMPLEMENTED:
1241 return ("NOT_IMPLEMENTED");
1242 case SIP_BAD_GATEWAY:
1243 return ("BAD_GATEWAY");
1244 case SIP_SERVICE_UNAVAILABLE:
1245 return ("SERVICE_UNAVAILABLE");
1246 case SIP_SERVER_TIMEOUT:
1247 return ("SERVER_TIMEOUT");
1248 case SIP_VERSION_NOT_SUPPORTED:
1249 return ("VERSION_NOT_SUPPORTED");
1250 case SIP_MESSAGE_2_LARGE:
1251 return ("MESSAGE_2_LARGE");
1252 case SIP_BUSY_EVERYWHERE:
1253 return ("BUSY_EVERYWHERE");
1254 case SIP_DECLINE:
1255 return ("DECLINE");
1256 case SIP_DOES_NOT_EXIST_ANYWHERE:
1257 return ("DOES_NOT_EXIST_ANYWHERE");
1258 case SIP_NOT_ACCEPTABLE_ANYWHERE:
1259 return ("NOT_ACCEPTABLE_ANYWHERE");
1260 default:
1261 return ("UNKNOWN");
1266 * The following three fns initialize and destroy the private library
1267 * data in sip_conn_object_t. The assumption is that the 1st member
1268 * of sip_conn_object_t is reserved for library use. The private data
1269 * is used only for byte-stream protocols such as TCP to accumulate
1270 * a complete SIP message, based on the CONTENT-LENGTH value, before
1271 * processing it.
1274 sip_init_conn_object(sip_conn_object_t obj)
1276 void **obj_val;
1277 sip_conn_obj_pvt_t *pvt_data;
1279 if (obj == NULL)
1280 return (EINVAL);
1281 pvt_data = malloc(sizeof (sip_conn_obj_pvt_t));
1282 if (pvt_data == NULL)
1283 return (ENOMEM);
1284 pvt_data->sip_conn_obj_cache = NULL;
1285 pvt_data->sip_conn_obj_reass = malloc(sizeof (sip_reass_entry_t));
1286 if (pvt_data->sip_conn_obj_reass == NULL) {
1287 free(pvt_data);
1288 return (ENOMEM);
1290 bzero(pvt_data->sip_conn_obj_reass, sizeof (sip_reass_entry_t));
1291 (void) pthread_mutex_init(&pvt_data->sip_conn_obj_reass_lock, NULL);
1292 (void) pthread_mutex_init(&pvt_data->sip_conn_obj_cache_lock, NULL);
1293 sip_refhold_conn(obj);
1294 obj_val = (void *)obj;
1295 *obj_val = (void *)pvt_data;
1297 return (0);
1301 * Clear private date, if any
1303 void
1304 sip_clear_stale_data(sip_conn_object_t obj)
1306 void **obj_val;
1307 sip_conn_obj_pvt_t *pvt_data;
1308 sip_reass_entry_t *reass;
1310 if (obj == NULL)
1311 return;
1312 obj_val = (void *)obj;
1313 pvt_data = (sip_conn_obj_pvt_t *)*obj_val;
1314 (void) pthread_mutex_lock(&pvt_data->sip_conn_obj_reass_lock);
1315 reass = pvt_data->sip_conn_obj_reass;
1316 if (reass->sip_reass_msg != NULL) {
1317 assert(reass->sip_reass_msglen > 0);
1318 free(reass->sip_reass_msg);
1319 reass->sip_reass_msglen = 0;
1321 assert(reass->sip_reass_msglen == 0);
1322 (void) pthread_mutex_unlock(&pvt_data->sip_conn_obj_reass_lock);
1326 * Walk through all the transactions, remove if this obj has been cached
1327 * by any.
1329 void
1330 sip_conn_destroyed(sip_conn_object_t obj)
1332 void **obj_val;
1333 sip_conn_obj_pvt_t *pvt_data;
1335 if (obj == NULL)
1336 return;
1337 obj_val = (void *)obj;
1338 pvt_data = (sip_conn_obj_pvt_t *)*obj_val;
1340 sip_clear_stale_data(obj);
1341 free(pvt_data->sip_conn_obj_reass);
1342 pvt_data->sip_conn_obj_reass = NULL;
1343 (void) pthread_mutex_destroy(&pvt_data->sip_conn_obj_reass_lock);
1345 sip_del_conn_obj_cache(obj, NULL);
1346 (void) pthread_mutex_destroy(&pvt_data->sip_conn_obj_cache_lock);
1348 free(pvt_data);
1349 *obj_val = NULL;
1350 sip_refrele_conn(obj);