140cb5e5dSvi117747 /*
240cb5e5dSvi117747 * CDDL HEADER START
340cb5e5dSvi117747 *
440cb5e5dSvi117747 * The contents of this file are subject to the terms of the
540cb5e5dSvi117747 * Common Development and Distribution License (the "License").
640cb5e5dSvi117747 * You may not use this file except in compliance with the License.
740cb5e5dSvi117747 *
840cb5e5dSvi117747 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
940cb5e5dSvi117747 * or http://www.opensolaris.org/os/licensing.
1040cb5e5dSvi117747 * See the License for the specific language governing permissions
1140cb5e5dSvi117747 * and limitations under the License.
1240cb5e5dSvi117747 *
1340cb5e5dSvi117747 * When distributing Covered Code, include this CDDL HEADER in each
1440cb5e5dSvi117747 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1540cb5e5dSvi117747 * If applicable, add the following below this CDDL HEADER, with the
1640cb5e5dSvi117747 * fields enclosed by brackets "[]" replaced with your own identifying
1740cb5e5dSvi117747 * information: Portions Copyright [yyyy] [name of copyright owner]
1840cb5e5dSvi117747 *
1940cb5e5dSvi117747 * CDDL HEADER END
2040cb5e5dSvi117747 */
2140cb5e5dSvi117747
2240cb5e5dSvi117747 /*
232c2c4183Svi117747 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
2440cb5e5dSvi117747 * Use is subject to license terms.
2540cb5e5dSvi117747 */
2640cb5e5dSvi117747
2740cb5e5dSvi117747 #pragma ident "%Z%%M% %I% %E% SMI"
2840cb5e5dSvi117747
292c2c4183Svi117747 #include <stdio.h>
302c2c4183Svi117747 #include <assert.h>
312c2c4183Svi117747 #include <errno.h>
322c2c4183Svi117747 #include <pthread.h>
332c2c4183Svi117747 #include <stdlib.h>
342c2c4183Svi117747 #include <string.h>
352c2c4183Svi117747 #include <sip.h>
362c2c4183Svi117747
3740cb5e5dSvi117747 #include "sip_msg.h"
3840cb5e5dSvi117747 #include "sip_miscdefs.h"
3940cb5e5dSvi117747 #include "sip_parse_generic.h"
4040cb5e5dSvi117747
4140cb5e5dSvi117747 sip_methods_t sip_methods[MAX_SIP_METHODS] = {
4240cb5e5dSvi117747 {"UNKNOWN", 7},
4340cb5e5dSvi117747 {"INVITE", 6},
4440cb5e5dSvi117747 {"ACK", 3},
4540cb5e5dSvi117747 {"OPTIONS", 7},
4640cb5e5dSvi117747 {"BYE", 3},
4740cb5e5dSvi117747 {"CANCEL", 6},
4840cb5e5dSvi117747 {"REGISTER", 8},
4940cb5e5dSvi117747 {"REFER", 5},
5040cb5e5dSvi117747 {"INFO", 4},
5140cb5e5dSvi117747 {"SUBSCRIBE", 9},
5240cb5e5dSvi117747 {"NOTIFY", 6},
5340cb5e5dSvi117747 {"PRACK", 5}
5440cb5e5dSvi117747 };
5540cb5e5dSvi117747
5640cb5e5dSvi117747 /*
5740cb5e5dSvi117747 * Built-In Header function table
5840cb5e5dSvi117747 */
5940cb5e5dSvi117747 sip_header_function_t sip_header_function_table[] = {
6040cb5e5dSvi117747 {"Unknown", NULL, sip_parse_unknown_header, NULL, NULL, NULL},
6140cb5e5dSvi117747 {"CONTACT", "m", sip_parse_cftr_header, NULL, NULL,
6240cb5e5dSvi117747 sip_free_cftr_header},
6340cb5e5dSvi117747 {"FROM", "F", sip_parse_cftr_header, NULL, NULL, sip_free_cftr_header},
6440cb5e5dSvi117747 {"TO", "T", sip_parse_cftr_header, NULL, NULL, sip_free_cftr_header},
6540cb5e5dSvi117747 {"CONTENT-LENGTH", "l", sip_parse_clen_header, NULL, NULL,
6640cb5e5dSvi117747 sip_free_phdr},
6740cb5e5dSvi117747 {"CONTENT-TYPE", "c", sip_parse_ctype_header, NULL, NULL,
6840cb5e5dSvi117747 sip_free_phdr},
6940cb5e5dSvi117747 {"CALL-ID", "i", sip_parse_cid_header, NULL, NULL, sip_free_phdr},
7040cb5e5dSvi117747 {"CSEQ", NULL, sip_parse_cseq_header, NULL, NULL, sip_free_phdr},
7140cb5e5dSvi117747 {"VIA", "v", sip_parse_via_header, NULL, NULL, sip_free_phdr},
7240cb5e5dSvi117747 {"Max-Forwards", NULL, sip_parse_maxf_header, NULL, NULL,
7340cb5e5dSvi117747 sip_free_phdr},
7440cb5e5dSvi117747 {"RECORD-ROUTE", NULL, sip_parse_cftr_header, NULL, NULL,
7540cb5e5dSvi117747 sip_free_cftr_header},
7640cb5e5dSvi117747 {"ROUTE", NULL, sip_parse_cftr_header, NULL, NULL,
7740cb5e5dSvi117747 sip_free_cftr_header},
7840cb5e5dSvi117747 {"ACCEPT", NULL, sip_parse_acpt_header, NULL, NULL, sip_free_phdr},
7940cb5e5dSvi117747 {"ACCEPT-ENCODING", NULL, sip_parse_acpt_encode_header, NULL, NULL,
8040cb5e5dSvi117747 sip_free_phdr},
8140cb5e5dSvi117747 {"ACCEPT-LANGUAGE", NULL, sip_parse_acpt_lang_header, NULL, NULL,
8240cb5e5dSvi117747 sip_free_phdr},
8340cb5e5dSvi117747 {"ALERT-INFO", NULL, sip_parse_alert_header, NULL, NULL, sip_free_phdr},
8440cb5e5dSvi117747 {"ALLOW", NULL, sip_parse_allow_header, NULL, NULL, sip_free_phdr},
8540cb5e5dSvi117747 {"CALL-INFO", NULL, sip_parse_callinfo_header, NULL, NULL,
8640cb5e5dSvi117747 sip_free_phdr},
8740cb5e5dSvi117747 {"CONTENT-DISPOSITION", NULL, sip_parse_contentdis_header, NULL, NULL,
8840cb5e5dSvi117747 sip_free_phdr},
8940cb5e5dSvi117747 {"CONTENT-ENCODING", "e", sip_parse_contentencode_header, NULL, NULL,
9040cb5e5dSvi117747 sip_free_phdr},
9140cb5e5dSvi117747 {"CONTENT-LANGUAGE", NULL, sip_parse_contentlang_header, NULL, NULL,
9240cb5e5dSvi117747 sip_free_phdr},
9340cb5e5dSvi117747 {"DATE", NULL, sip_parse_date_header, NULL, NULL, sip_free_phdr},
9440cb5e5dSvi117747 {"ERROR-INFO", NULL, sip_parse_errorinfo_header, NULL, NULL,
9540cb5e5dSvi117747 sip_free_phdr},
9640cb5e5dSvi117747 {"EXPIRES", NULL, sip_parse_expire_header, NULL, NULL, sip_free_phdr},
9740cb5e5dSvi117747 {"IN-REPLY-TO", NULL, sip_parse_inreplyto_header, NULL, NULL,
9840cb5e5dSvi117747 sip_free_phdr},
9940cb5e5dSvi117747 {"MIN-EXPIRES", NULL, sip_parse_minexpire_header, NULL, NULL,
10040cb5e5dSvi117747 sip_free_phdr},
10140cb5e5dSvi117747 {"MIME-VERSION", NULL, sip_parse_mimeversion_header, NULL, NULL,
10240cb5e5dSvi117747 sip_free_phdr},
10340cb5e5dSvi117747 {"ORGANIZATION", NULL, sip_parse_org_header, NULL, NULL, sip_free_phdr},
10440cb5e5dSvi117747 {"PRIORITY", NULL, sip_parse_priority_header, NULL, NULL,
10540cb5e5dSvi117747 sip_free_phdr},
10640cb5e5dSvi117747 {"REQUIRE", NULL, sip_parse_require_header, NULL, NULL, sip_free_phdr},
10740cb5e5dSvi117747 {"REPLY-TO", NULL, sip_parse_replyto_header, NULL, NULL, sip_free_phdr},
10840cb5e5dSvi117747 {"RETRY-AFTER", NULL, sip_parse_retryaft_header, NULL, NULL,
10940cb5e5dSvi117747 sip_free_phdr},
11040cb5e5dSvi117747 {"SERVER", NULL, sip_parse_server_header, NULL, NULL, sip_free_phdr},
11140cb5e5dSvi117747 {"SUBJECT", "s", sip_parse_subject_header, NULL, NULL, sip_free_phdr},
11240cb5e5dSvi117747 {"TIMESTAMP", NULL, sip_parse_timestamp_header, NULL, NULL,
11340cb5e5dSvi117747 sip_free_phdr},
11440cb5e5dSvi117747 {"UNSUPPORTED", NULL, sip_parse_usupport_header, NULL, NULL,
11540cb5e5dSvi117747 sip_free_phdr},
11640cb5e5dSvi117747 {"SUPPORTED", "k", sip_parse_support_header, NULL, NULL, sip_free_phdr},
11740cb5e5dSvi117747 {"USER-AGENT", NULL, sip_parse_useragt_header, NULL, NULL,
11840cb5e5dSvi117747 sip_free_phdr},
11940cb5e5dSvi117747 {"WARNING", NULL, sip_parse_warn_header, NULL, NULL, sip_free_phdr},
12040cb5e5dSvi117747 {"ALLOW-EVENTS", "u", sip_parse_allow_events_header, NULL, NULL,
12140cb5e5dSvi117747 sip_free_phdr},
12240cb5e5dSvi117747 {"EVENT", "o", sip_parse_event_header, NULL, NULL, sip_free_phdr},
12340cb5e5dSvi117747 {"SUBSCRIPTION-STATE", NULL, sip_parse_substate_header, NULL, NULL,
12440cb5e5dSvi117747 sip_free_phdr},
12540cb5e5dSvi117747 {"AUTHORIZATION", NULL, sip_parse_author_header, NULL, NULL,
12640cb5e5dSvi117747 sip_free_phdr},
12740cb5e5dSvi117747 {"AUTHENTICATION-INFO", NULL, sip_parse_ainfo_header, NULL, NULL,
12840cb5e5dSvi117747 sip_free_phdr},
12940cb5e5dSvi117747 {"PROXY-AUTHORIZATION", NULL, sip_parse_pauthor_header, NULL, NULL,
13040cb5e5dSvi117747 sip_free_phdr},
13140cb5e5dSvi117747 {"PROXY-AUTHENTICATE", NULL, sip_parse_pauthen_header, NULL, NULL,
13240cb5e5dSvi117747 sip_free_phdr},
13340cb5e5dSvi117747 {"PROXY-REQUIRE", NULL, sip_parse_preq_header, NULL, NULL,
13440cb5e5dSvi117747 sip_free_phdr},
13540cb5e5dSvi117747 {"WWW-AUTHENTICATE", NULL, sip_parse_wauthen_header, NULL, NULL,
13640cb5e5dSvi117747 sip_free_phdr},
13740cb5e5dSvi117747 {"RSEQ", NULL, sip_parse_rseq, NULL, NULL, sip_free_phdr},
13840cb5e5dSvi117747 {"RACK", NULL, sip_parse_rack, NULL, NULL, sip_free_phdr},
13940cb5e5dSvi117747 {"P-ASSERTED-IDENTITY", NULL, sip_parse_passertedid, NULL, NULL,
14040cb5e5dSvi117747 sip_free_phdr},
14140cb5e5dSvi117747 {"P-PREFERRED-IDENTITY", NULL, sip_parse_ppreferredid, NULL, NULL,
14240cb5e5dSvi117747 sip_free_phdr},
14340cb5e5dSvi117747 {"PRIVACY", NULL, sip_parse_privacy_header, NULL, NULL, sip_free_phdr},
14440cb5e5dSvi117747 {NULL, NULL, NULL, NULL, NULL, NULL},
14540cb5e5dSvi117747 };
14640cb5e5dSvi117747
14740cb5e5dSvi117747 #define MAX_SIP_HEADERS \
14840cb5e5dSvi117747 sizeof (sip_header_function_table) / sizeof (sip_header_function_t)
14940cb5e5dSvi117747
15040cb5e5dSvi117747 /*
15140cb5e5dSvi117747 * External/application provided function table
15240cb5e5dSvi117747 */
15340cb5e5dSvi117747 sip_header_function_t *sip_header_function_table_external = NULL;
15440cb5e5dSvi117747
15540cb5e5dSvi117747 /*
15640cb5e5dSvi117747 * Free parameter list
15740cb5e5dSvi117747 */
15840cb5e5dSvi117747 static void
sip_free_params(sip_param_t * param_list)15940cb5e5dSvi117747 sip_free_params(sip_param_t *param_list)
16040cb5e5dSvi117747 {
16140cb5e5dSvi117747 sip_param_t *param, *next_param;
16240cb5e5dSvi117747
16340cb5e5dSvi117747 param = param_list;
16440cb5e5dSvi117747
16540cb5e5dSvi117747 while (param != NULL) {
16640cb5e5dSvi117747 next_param = param->param_next;
16740cb5e5dSvi117747 free(param);
16840cb5e5dSvi117747 param = next_param;
16940cb5e5dSvi117747 }
17040cb5e5dSvi117747 }
17140cb5e5dSvi117747
17240cb5e5dSvi117747 /*
17340cb5e5dSvi117747 * Common header free routine
17440cb5e5dSvi117747 */
17540cb5e5dSvi117747 void
sip_free_phdr(sip_parsed_header_t * header)17640cb5e5dSvi117747 sip_free_phdr(sip_parsed_header_t *header)
17740cb5e5dSvi117747 {
17840cb5e5dSvi117747 sip_hdr_value_t *value;
17940cb5e5dSvi117747 sip_hdr_value_t *next_value;
18040cb5e5dSvi117747
18140cb5e5dSvi117747 if (header == NULL)
18240cb5e5dSvi117747 return;
18340cb5e5dSvi117747 value = (sip_hdr_value_t *)header->value;
18440cb5e5dSvi117747 while (value != NULL) {
18540cb5e5dSvi117747 sip_free_params(value->sip_param_list);
18640cb5e5dSvi117747 next_value = value->sip_next_value;
18740cb5e5dSvi117747 free(value);
18840cb5e5dSvi117747 value = next_value;
18940cb5e5dSvi117747 }
19040cb5e5dSvi117747 free(header);
19140cb5e5dSvi117747 }
19240cb5e5dSvi117747
19340cb5e5dSvi117747 /*
19440cb5e5dSvi117747 * Free Contact/From/To header
19540cb5e5dSvi117747 */
19640cb5e5dSvi117747 void
sip_free_cftr_header(sip_parsed_header_t * header)19740cb5e5dSvi117747 sip_free_cftr_header(sip_parsed_header_t *header)
19840cb5e5dSvi117747 {
19940cb5e5dSvi117747 sip_hdr_value_t *value;
20040cb5e5dSvi117747 sip_hdr_value_t *next_value;
20140cb5e5dSvi117747
20240cb5e5dSvi117747 if (header == NULL)
20340cb5e5dSvi117747 return;
20440cb5e5dSvi117747 value = (sip_hdr_value_t *)header->value;
20540cb5e5dSvi117747 while (value != NULL) {
20640cb5e5dSvi117747 next_value = value->sip_next_value;
20740cb5e5dSvi117747 sip_free_params(value->sip_param_list);
20840cb5e5dSvi117747 if (value->cftr_name != NULL)
20940cb5e5dSvi117747 free(value->cftr_name);
21040cb5e5dSvi117747 if (value->sip_value_parsed_uri != NULL) {
21140cb5e5dSvi117747 sip_free_parsed_uri(value->sip_value_parsed_uri);
21240cb5e5dSvi117747 value->sip_value_parsed_uri = NULL;
21340cb5e5dSvi117747 }
21440cb5e5dSvi117747 free(value);
21540cb5e5dSvi117747 value = next_value;
21640cb5e5dSvi117747 }
21740cb5e5dSvi117747 free(header);
21840cb5e5dSvi117747 }
21940cb5e5dSvi117747
22040cb5e5dSvi117747 /*
22140cb5e5dSvi117747 * Return new header
22240cb5e5dSvi117747 */
22340cb5e5dSvi117747 _sip_header_t *
sip_new_header(int header_size)22440cb5e5dSvi117747 sip_new_header(int header_size)
22540cb5e5dSvi117747 {
22640cb5e5dSvi117747 _sip_header_t *new_header;
22740cb5e5dSvi117747
22840cb5e5dSvi117747 new_header = calloc(1, sizeof (_sip_header_t));
22940cb5e5dSvi117747 if (new_header == NULL)
23040cb5e5dSvi117747 return (NULL);
23140cb5e5dSvi117747
23240cb5e5dSvi117747 /*
23340cb5e5dSvi117747 * We are using snprintf which adds a null character
23440cb5e5dSvi117747 * so allocate an extra byte which is not part of
23540cb5e5dSvi117747 * the message header
23640cb5e5dSvi117747 */
23740cb5e5dSvi117747 new_header->sip_hdr_start = calloc(1, header_size + 1);
23840cb5e5dSvi117747 if (new_header->sip_hdr_start == NULL) {
23940cb5e5dSvi117747 free(new_header);
24040cb5e5dSvi117747 return (NULL);
24140cb5e5dSvi117747 }
24240cb5e5dSvi117747 new_header->sip_hdr_end = new_header->sip_hdr_start + header_size;
24340cb5e5dSvi117747 new_header->sip_hdr_current = new_header->sip_hdr_start;
24440cb5e5dSvi117747 new_header->sip_hdr_allocated = B_TRUE;
24540cb5e5dSvi117747 return (new_header);
24640cb5e5dSvi117747 }
24740cb5e5dSvi117747
24840cb5e5dSvi117747 /*
24940cb5e5dSvi117747 * Free the given header
25040cb5e5dSvi117747 */
25140cb5e5dSvi117747 void
sip_free_header(_sip_header_t * sip_header)25240cb5e5dSvi117747 sip_free_header(_sip_header_t *sip_header)
25340cb5e5dSvi117747 {
25440cb5e5dSvi117747 if (sip_header->sip_hdr_allocated) {
25540cb5e5dSvi117747 assert(sip_header->sip_hdr_start != NULL);
25640cb5e5dSvi117747 free(sip_header->sip_hdr_start);
25740cb5e5dSvi117747 }
25840cb5e5dSvi117747 if (sip_header->sip_hdr_parsed != NULL) {
25940cb5e5dSvi117747 assert(sip_header->sip_header_functions != NULL);
26040cb5e5dSvi117747 if (sip_header->sip_header_functions->header_free != NULL) {
26140cb5e5dSvi117747 sip_header->sip_header_functions->header_free(
26240cb5e5dSvi117747 sip_header->sip_hdr_parsed);
26340cb5e5dSvi117747 }
26440cb5e5dSvi117747 }
26540cb5e5dSvi117747 free(sip_header);
26640cb5e5dSvi117747 }
26740cb5e5dSvi117747
26840cb5e5dSvi117747 /*
26940cb5e5dSvi117747 * Return a copy of the header passed in.
27040cb5e5dSvi117747 */
27140cb5e5dSvi117747 _sip_header_t *
sip_dup_header(_sip_header_t * from)27240cb5e5dSvi117747 sip_dup_header(_sip_header_t *from)
27340cb5e5dSvi117747 {
27440cb5e5dSvi117747 size_t hdr_size;
27540cb5e5dSvi117747 _sip_header_t *to;
27640cb5e5dSvi117747
27740cb5e5dSvi117747 hdr_size = from->sip_hdr_end - from->sip_hdr_start;
27840cb5e5dSvi117747 to = sip_new_header(hdr_size);
27940cb5e5dSvi117747 if (to == NULL)
28040cb5e5dSvi117747 return (NULL);
28140cb5e5dSvi117747 if (from->sip_header_state == SIP_HEADER_DELETED_VAL) {
28240cb5e5dSvi117747 to->sip_hdr_end = to->sip_hdr_start +
28340cb5e5dSvi117747 sip_copy_values(to->sip_hdr_start, from);
28440cb5e5dSvi117747 } else {
28540cb5e5dSvi117747 (void) memcpy(to->sip_hdr_start, from->sip_hdr_start, hdr_size);
28640cb5e5dSvi117747 to->sip_hdr_end = to->sip_hdr_start + hdr_size;
28740cb5e5dSvi117747 }
28840cb5e5dSvi117747 to->sip_header_functions = from->sip_header_functions;
28940cb5e5dSvi117747 return (to);
29040cb5e5dSvi117747 }
29140cb5e5dSvi117747
29240cb5e5dSvi117747 /*
29340cb5e5dSvi117747 * Copy header with extra_param, if any, to sip_msg
29440cb5e5dSvi117747 */
29540cb5e5dSvi117747 int
_sip_copy_header(_sip_msg_t * sip_msg,_sip_header_t * header,char * extra_param,boolean_t skip_crlf)29640cb5e5dSvi117747 _sip_copy_header(_sip_msg_t *sip_msg, _sip_header_t *header, char *extra_param,
29740cb5e5dSvi117747 boolean_t skip_crlf)
29840cb5e5dSvi117747 {
29940cb5e5dSvi117747 _sip_header_t *new_header;
30040cb5e5dSvi117747 int hdrlen;
30140cb5e5dSvi117747 int extra_len = 0;
30240cb5e5dSvi117747 int ncrlf = 0;
30340cb5e5dSvi117747 char *p;
30440cb5e5dSvi117747
30540cb5e5dSvi117747 #ifdef __solaris__
30640cb5e5dSvi117747 assert(mutex_held(&sip_msg->sip_msg_mutex));
30740cb5e5dSvi117747 #endif
30840cb5e5dSvi117747 if (extra_param != NULL) {
30940cb5e5dSvi117747 extra_len = SIP_SPACE_LEN + sizeof (char) + SIP_SPACE_LEN +
31040cb5e5dSvi117747 strlen(extra_param);
31140cb5e5dSvi117747 }
31240cb5e5dSvi117747 /*
31340cb5e5dSvi117747 * Just take one if there are more, i.e. if this is the last header
31440cb5e5dSvi117747 * before the content.
31540cb5e5dSvi117747 */
31640cb5e5dSvi117747 if (skip_crlf) {
31740cb5e5dSvi117747 if (header->sip_hdr_end - strlen(SIP_CRLF) <=
31840cb5e5dSvi117747 header->sip_hdr_start) {
31940cb5e5dSvi117747 goto proceed;
32040cb5e5dSvi117747 }
32140cb5e5dSvi117747 p = header->sip_hdr_end - strlen(SIP_CRLF);
32240cb5e5dSvi117747 while (strncmp(SIP_CRLF, p, strlen(SIP_CRLF)) == 0) {
32340cb5e5dSvi117747 ncrlf++;
32440cb5e5dSvi117747 if (p - strlen(SIP_CRLF) < header->sip_hdr_start)
32540cb5e5dSvi117747 break;
32640cb5e5dSvi117747 p -= strlen(SIP_CRLF);
32740cb5e5dSvi117747 }
32840cb5e5dSvi117747 /*
32940cb5e5dSvi117747 * Take one CRLF.
33040cb5e5dSvi117747 */
33140cb5e5dSvi117747 ncrlf = (ncrlf - 1) * strlen(SIP_CRLF);
33240cb5e5dSvi117747 }
33340cb5e5dSvi117747 proceed:
33440cb5e5dSvi117747 hdrlen = header->sip_hdr_end - header->sip_hdr_start - ncrlf;
33540cb5e5dSvi117747 new_header = sip_new_header(hdrlen + extra_len);
33640cb5e5dSvi117747 if (new_header == NULL)
33740cb5e5dSvi117747 return (ENOMEM);
33840cb5e5dSvi117747 if (header->sip_header_state == SIP_HEADER_DELETED_VAL) {
33940cb5e5dSvi117747 int len;
34040cb5e5dSvi117747
34140cb5e5dSvi117747 len = sip_copy_values(new_header->sip_hdr_start, header);
34240cb5e5dSvi117747 new_header->sip_hdr_end = new_header->sip_hdr_start + len;
34340cb5e5dSvi117747 hdrlen = hdrlen - len + extra_len;
34440cb5e5dSvi117747 } else {
34540cb5e5dSvi117747 (void) memcpy(new_header->sip_hdr_start, header->sip_hdr_start,
34640cb5e5dSvi117747 hdrlen);
34740cb5e5dSvi117747 new_header->sip_hdr_end = new_header->sip_hdr_start + hdrlen;
34840cb5e5dSvi117747 hdrlen = extra_len;
34940cb5e5dSvi117747 }
35040cb5e5dSvi117747 if (extra_param != NULL) {
35140cb5e5dSvi117747 /*
35240cb5e5dSvi117747 * Find CR
35340cb5e5dSvi117747 */
35440cb5e5dSvi117747 if (sip_find_cr(new_header) != 0) {
35540cb5e5dSvi117747 sip_free_header(new_header);
35640cb5e5dSvi117747 return (EINVAL);
35740cb5e5dSvi117747 }
35840cb5e5dSvi117747 hdrlen += new_header->sip_hdr_end - new_header->sip_hdr_current;
35940cb5e5dSvi117747 (void) snprintf(new_header->sip_hdr_current, hdrlen + 1,
36040cb5e5dSvi117747 " %c %s%s", SIP_SEMI, extra_param, SIP_CRLF);
36140cb5e5dSvi117747 }
36240cb5e5dSvi117747
36340cb5e5dSvi117747 new_header->sip_hdr_end += extra_len;
36440cb5e5dSvi117747 new_header->sip_header_functions = header->sip_header_functions;
36540cb5e5dSvi117747 _sip_add_header(sip_msg, new_header, B_TRUE, B_FALSE, NULL);
36640cb5e5dSvi117747 return (0);
36740cb5e5dSvi117747 }
36840cb5e5dSvi117747
36940cb5e5dSvi117747 /*
37040cb5e5dSvi117747 * Copy all "header_name" headers from _old_msg to _new_msg
37140cb5e5dSvi117747 */
37240cb5e5dSvi117747 int
_sip_find_and_copy_all_header(_sip_msg_t * _old_msg,_sip_msg_t * _new_msg,char * header_name)37340cb5e5dSvi117747 _sip_find_and_copy_all_header(_sip_msg_t *_old_msg, _sip_msg_t *_new_msg,
37440cb5e5dSvi117747 char *header_name)
37540cb5e5dSvi117747 {
37640cb5e5dSvi117747 _sip_header_t *header;
37740cb5e5dSvi117747 int ret = 0;
37840cb5e5dSvi117747
37940cb5e5dSvi117747 if (_old_msg == NULL || _new_msg == NULL)
38040cb5e5dSvi117747 return (EINVAL);
38140cb5e5dSvi117747 #ifdef __solaris__
38240cb5e5dSvi117747 assert(mutex_held(&_old_msg->sip_msg_mutex));
38340cb5e5dSvi117747 #endif
38440cb5e5dSvi117747 if (_old_msg != _new_msg)
38540cb5e5dSvi117747 (void) pthread_mutex_lock(&_new_msg->sip_msg_mutex);
38640cb5e5dSvi117747 header = sip_search_for_header(_old_msg, header_name, NULL);
38740cb5e5dSvi117747 while (header != NULL) {
38840cb5e5dSvi117747 ret = _sip_copy_header(_new_msg, header, NULL, B_TRUE);
38940cb5e5dSvi117747 if (ret != 0)
39040cb5e5dSvi117747 break;
39140cb5e5dSvi117747 header = sip_search_for_header(_old_msg, header_name, header);
39240cb5e5dSvi117747 }
39340cb5e5dSvi117747 if (_old_msg != _new_msg)
39440cb5e5dSvi117747 (void) pthread_mutex_unlock(&_new_msg->sip_msg_mutex);
39540cb5e5dSvi117747 return (ret);
39640cb5e5dSvi117747 }
39740cb5e5dSvi117747
39840cb5e5dSvi117747 /*
39940cb5e5dSvi117747 * Copy header_name from _old_msg to _new_msg with extra_parm.
40040cb5e5dSvi117747 */
40140cb5e5dSvi117747 int
_sip_find_and_copy_header(sip_msg_t _old_msg,sip_msg_t _new_msg,char * header_name,char * extra_param,boolean_t lock_newmsg)40240cb5e5dSvi117747 _sip_find_and_copy_header(sip_msg_t _old_msg, sip_msg_t _new_msg,
40340cb5e5dSvi117747 char *header_name, char *extra_param, boolean_t lock_newmsg)
40440cb5e5dSvi117747 {
40540cb5e5dSvi117747 _sip_header_t *header;
40640cb5e5dSvi117747 int ret;
40740cb5e5dSvi117747
40840cb5e5dSvi117747 if (_old_msg == NULL || _new_msg == NULL)
40940cb5e5dSvi117747 return (EINVAL);
41040cb5e5dSvi117747 #ifdef __solaris__
41140cb5e5dSvi117747 assert(mutex_held(&_old_msg->sip_msg_mutex));
41240cb5e5dSvi117747 #endif
41340cb5e5dSvi117747 header = sip_search_for_header(_old_msg, header_name, NULL);
41440cb5e5dSvi117747 if (header == NULL)
41540cb5e5dSvi117747 return (EINVAL);
41640cb5e5dSvi117747 if (lock_newmsg)
41740cb5e5dSvi117747 (void) pthread_mutex_lock(&_new_msg->sip_msg_mutex);
41840cb5e5dSvi117747 ret = _sip_copy_header(_new_msg, header, extra_param, B_TRUE);
41940cb5e5dSvi117747 if (lock_newmsg)
42040cb5e5dSvi117747 (void) pthread_mutex_unlock(&_new_msg->sip_msg_mutex);
42140cb5e5dSvi117747 return (ret);
42240cb5e5dSvi117747 }
42340cb5e5dSvi117747
42440cb5e5dSvi117747 /*
42540cb5e5dSvi117747 * Copy all headers from old_msg to new_msg
42640cb5e5dSvi117747 */
42740cb5e5dSvi117747 int
sip_copy_all_headers(sip_msg_t old_msg,sip_msg_t new_msg)42840cb5e5dSvi117747 sip_copy_all_headers(sip_msg_t old_msg, sip_msg_t new_msg)
42940cb5e5dSvi117747 {
43040cb5e5dSvi117747 _sip_header_t *header;
43140cb5e5dSvi117747 _sip_msg_t *_old_msg;
43240cb5e5dSvi117747 _sip_msg_t *_new_msg;
43340cb5e5dSvi117747 int ret = 0;
43440cb5e5dSvi117747
43540cb5e5dSvi117747 if (old_msg == NULL || new_msg == NULL)
43640cb5e5dSvi117747 return (EINVAL);
43740cb5e5dSvi117747 _old_msg = (_sip_msg_t *)old_msg;
43840cb5e5dSvi117747 _new_msg = (_sip_msg_t *)new_msg;
43940cb5e5dSvi117747
44040cb5e5dSvi117747 (void) pthread_mutex_lock(&_old_msg->sip_msg_mutex);
44140cb5e5dSvi117747 (void) pthread_mutex_lock(&_new_msg->sip_msg_mutex);
44240cb5e5dSvi117747 header = sip_search_for_header(_old_msg, NULL, NULL);
44340cb5e5dSvi117747 while (header != NULL) {
44440cb5e5dSvi117747 ret = _sip_copy_header(_new_msg, header, NULL, B_FALSE);
44540cb5e5dSvi117747 if (ret != 0)
44640cb5e5dSvi117747 goto done;
44740cb5e5dSvi117747 header = sip_search_for_header(_old_msg, NULL, header);
44840cb5e5dSvi117747 }
44940cb5e5dSvi117747 done:
45040cb5e5dSvi117747 (void) pthread_mutex_unlock(&_new_msg->sip_msg_mutex);
45140cb5e5dSvi117747 (void) pthread_mutex_unlock(&_old_msg->sip_msg_mutex);
45240cb5e5dSvi117747 return (ret);
45340cb5e5dSvi117747 }
45440cb5e5dSvi117747
45540cb5e5dSvi117747 /*
45640cb5e5dSvi117747 * Copy start line from msg to sip_msg
45740cb5e5dSvi117747 */
45840cb5e5dSvi117747 int
sip_copy_start_line(sip_msg_t msg,sip_msg_t sip_msg)45940cb5e5dSvi117747 sip_copy_start_line(sip_msg_t msg, sip_msg_t sip_msg)
46040cb5e5dSvi117747 {
46140cb5e5dSvi117747 int len;
46240cb5e5dSvi117747 _sip_header_t *new_header;
46340cb5e5dSvi117747 _sip_msg_t *_old_msg;
46440cb5e5dSvi117747 _sip_msg_t *_sip_msg;
46540cb5e5dSvi117747
46640cb5e5dSvi117747 if (msg == NULL || sip_msg == NULL)
46740cb5e5dSvi117747 return (EINVAL);
46840cb5e5dSvi117747 _old_msg = (_sip_msg_t *)msg;
46940cb5e5dSvi117747 _sip_msg = (_sip_msg_t *)sip_msg;
47040cb5e5dSvi117747
47140cb5e5dSvi117747 (void) pthread_mutex_lock(&_old_msg->sip_msg_mutex);
47240cb5e5dSvi117747 if (_old_msg->sip_msg_start_line == NULL) {
47340cb5e5dSvi117747 (void) pthread_mutex_unlock(&_old_msg->sip_msg_mutex);
47440cb5e5dSvi117747 return (EINVAL);
47540cb5e5dSvi117747 }
47640cb5e5dSvi117747 len = _old_msg->sip_msg_start_line->sip_hdr_end -
47740cb5e5dSvi117747 _old_msg->sip_msg_start_line->sip_hdr_start;
47840cb5e5dSvi117747 new_header = sip_new_header(len);
47940cb5e5dSvi117747 if (new_header == NULL) {
48040cb5e5dSvi117747 (void) pthread_mutex_unlock(&_old_msg->sip_msg_mutex);
48140cb5e5dSvi117747 return (ENOMEM);
48240cb5e5dSvi117747 }
48340cb5e5dSvi117747 new_header->sip_hdr_sipmsg = _sip_msg;
48440cb5e5dSvi117747 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
48540cb5e5dSvi117747 _sip_msg->sip_msg_start_line = new_header;
48640cb5e5dSvi117747 _sip_msg->sip_msg_len = len;
48740cb5e5dSvi117747 (void) strncpy(_sip_msg->sip_msg_start_line->sip_hdr_start,
48840cb5e5dSvi117747 _old_msg->sip_msg_start_line->sip_hdr_start, len);
48940cb5e5dSvi117747 (void) sip_parse_first_line(_sip_msg->sip_msg_start_line,
49040cb5e5dSvi117747 &_sip_msg->sip_msg_req_res);
49140cb5e5dSvi117747 (void) pthread_mutex_unlock(&_old_msg->sip_msg_mutex);
49240cb5e5dSvi117747 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
49340cb5e5dSvi117747 return (0);
49440cb5e5dSvi117747 }
49540cb5e5dSvi117747
49640cb5e5dSvi117747 /*
49740cb5e5dSvi117747 * Delete start line from sip_msg
49840cb5e5dSvi117747 */
49940cb5e5dSvi117747 int
sip_delete_start_line_locked(_sip_msg_t * _sip_msg)50040cb5e5dSvi117747 sip_delete_start_line_locked(_sip_msg_t *_sip_msg)
50140cb5e5dSvi117747 {
50240cb5e5dSvi117747 _sip_header_t *header;
50340cb5e5dSvi117747 _sip_header_t *next_header;
50440cb5e5dSvi117747
50540cb5e5dSvi117747 if (_sip_msg->sip_msg_start_line == NULL)
50640cb5e5dSvi117747 return (EINVAL);
50740cb5e5dSvi117747
50840cb5e5dSvi117747 header = _sip_msg->sip_msg_start_line;
50940cb5e5dSvi117747 while (header != NULL) {
51040cb5e5dSvi117747 next_header = header->sip_hdr_next;
51140cb5e5dSvi117747 _sip_msg->sip_msg_len -= (header->sip_hdr_end -
51240cb5e5dSvi117747 header->sip_hdr_start);
51340cb5e5dSvi117747 sip_free_header(header);
51440cb5e5dSvi117747 header = next_header;
51540cb5e5dSvi117747 }
51640cb5e5dSvi117747 _sip_msg->sip_msg_start_line = NULL;
51740cb5e5dSvi117747
51840cb5e5dSvi117747 /*
51940cb5e5dSvi117747 * Also delete the sip_msg_req_res info since we don't have a start
52040cb5e5dSvi117747 * line.
52140cb5e5dSvi117747 */
52240cb5e5dSvi117747 while (_sip_msg->sip_msg_req_res != NULL) {
52340cb5e5dSvi117747 sip_message_type_t *sip_msg_type_ptr;
52440cb5e5dSvi117747
52540cb5e5dSvi117747 sip_msg_type_ptr = _sip_msg->sip_msg_req_res->sip_next;
52640cb5e5dSvi117747 if (_sip_msg->sip_msg_req_res->is_request) {
52740cb5e5dSvi117747 sip_request_t *reqline;
52840cb5e5dSvi117747
52940cb5e5dSvi117747 reqline = &_sip_msg->sip_msg_req_res->U.sip_request;
53040cb5e5dSvi117747 if (reqline->sip_parse_uri != NULL) {
53140cb5e5dSvi117747 sip_free_parsed_uri(reqline->sip_parse_uri);
53240cb5e5dSvi117747 reqline->sip_parse_uri = NULL;
53340cb5e5dSvi117747 }
53440cb5e5dSvi117747 }
53540cb5e5dSvi117747 free(_sip_msg->sip_msg_req_res);
53640cb5e5dSvi117747 _sip_msg->sip_msg_req_res = sip_msg_type_ptr;
53740cb5e5dSvi117747 }
53840cb5e5dSvi117747 return (0);
53940cb5e5dSvi117747 }
54040cb5e5dSvi117747
54140cb5e5dSvi117747
54240cb5e5dSvi117747 /*
54340cb5e5dSvi117747 * Delete start line from sip_msg
54440cb5e5dSvi117747 */
54540cb5e5dSvi117747 int
sip_delete_start_line(sip_msg_t sip_msg)54640cb5e5dSvi117747 sip_delete_start_line(sip_msg_t sip_msg)
54740cb5e5dSvi117747 {
54840cb5e5dSvi117747 _sip_msg_t *_sip_msg;
54940cb5e5dSvi117747 int ret;
55040cb5e5dSvi117747
55140cb5e5dSvi117747 if (sip_msg == NULL)
55240cb5e5dSvi117747 return (EINVAL);
55340cb5e5dSvi117747
55440cb5e5dSvi117747 _sip_msg = (_sip_msg_t *)sip_msg;
55540cb5e5dSvi117747 (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
55640cb5e5dSvi117747 ret = sip_delete_start_line_locked(_sip_msg);
55740cb5e5dSvi117747 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
55840cb5e5dSvi117747
55940cb5e5dSvi117747 return (ret);
56040cb5e5dSvi117747 }
56140cb5e5dSvi117747
56240cb5e5dSvi117747 /*
56340cb5e5dSvi117747 * Delete all headers from _sip_msg
56440cb5e5dSvi117747 */
56540cb5e5dSvi117747 void
sip_delete_all_headers(_sip_msg_t * _sip_msg)56640cb5e5dSvi117747 sip_delete_all_headers(_sip_msg_t *_sip_msg)
56740cb5e5dSvi117747 {
56840cb5e5dSvi117747 _sip_header_t *header;
56940cb5e5dSvi117747
57040cb5e5dSvi117747 #ifdef __solaris__
57140cb5e5dSvi117747 assert(mutex_held(&_sip_msg->sip_msg_mutex));
57240cb5e5dSvi117747 #endif
57340cb5e5dSvi117747
57440cb5e5dSvi117747 header = _sip_msg->sip_msg_headers_start;
57540cb5e5dSvi117747 while (header != NULL) {
57640cb5e5dSvi117747 _sip_header_t *next_header;
57740cb5e5dSvi117747 next_header = header->sip_hdr_next;
57840cb5e5dSvi117747 sip_free_header(header);
57940cb5e5dSvi117747 header = next_header;
58040cb5e5dSvi117747 }
58140cb5e5dSvi117747 _sip_msg->sip_msg_headers_start = NULL;
58240cb5e5dSvi117747 _sip_msg->sip_msg_headers_end = NULL;
58340cb5e5dSvi117747 }
58440cb5e5dSvi117747
58540cb5e5dSvi117747 /*
58640cb5e5dSvi117747 * Delete and free the named header. If header_name is null
58740cb5e5dSvi117747 * free all headers.
58840cb5e5dSvi117747 */
58940cb5e5dSvi117747 void
sip_delete_headers(sip_msg_t sip_msg,char * header_name)59040cb5e5dSvi117747 sip_delete_headers(sip_msg_t sip_msg, char *header_name)
59140cb5e5dSvi117747 {
59240cb5e5dSvi117747 _sip_header_t *header;
59340cb5e5dSvi117747 _sip_msg_t *_sip_msg;
59440cb5e5dSvi117747
59540cb5e5dSvi117747 _sip_msg = (_sip_msg_t *)sip_msg;
59640cb5e5dSvi117747 #ifdef __solaris__
59740cb5e5dSvi117747 assert(mutex_held(&_sip_msg->sip_msg_mutex));
59840cb5e5dSvi117747 #endif
59940cb5e5dSvi117747 header = sip_search_for_header(_sip_msg, header_name, NULL);
60040cb5e5dSvi117747 if (header == NULL)
60140cb5e5dSvi117747 return;
60240cb5e5dSvi117747 while (header != NULL) {
60340cb5e5dSvi117747 if (_sip_msg->sip_msg_headers_start == header) {
60440cb5e5dSvi117747 _sip_msg->sip_msg_headers_start = header->sip_hdr_next;
60540cb5e5dSvi117747 } else {
60640cb5e5dSvi117747 header->sip_hdr_prev->sip_hdr_next =
60740cb5e5dSvi117747 header->sip_hdr_next;
60840cb5e5dSvi117747 }
60940cb5e5dSvi117747 if (_sip_msg->sip_msg_headers_end == header) {
61040cb5e5dSvi117747 _sip_msg->sip_msg_headers_end = header->sip_hdr_prev;
61140cb5e5dSvi117747 } else {
61240cb5e5dSvi117747 header->sip_hdr_next->sip_hdr_prev =
61340cb5e5dSvi117747 header->sip_hdr_prev;
61440cb5e5dSvi117747 }
61540cb5e5dSvi117747 sip_free_header(header);
61640cb5e5dSvi117747 if (header_name != NULL)
61740cb5e5dSvi117747 return;
61840cb5e5dSvi117747 else
61940cb5e5dSvi117747 header = sip_search_for_header(_sip_msg, NULL, NULL);
62040cb5e5dSvi117747 }
62140cb5e5dSvi117747 }
62240cb5e5dSvi117747
62340cb5e5dSvi117747 /*
62440cb5e5dSvi117747 * Add a header to sip_msg. If header_name is provided then the new header
62540cb5e5dSvi117747 * is added before that header, if first is set, or after. If append is
62640cb5e5dSvi117747 * set, then the header is added to the end of the header list.
62740cb5e5dSvi117747 */
62840cb5e5dSvi117747 void
_sip_add_header(_sip_msg_t * sip_msg,_sip_header_t * new_header,boolean_t append,boolean_t first,char * header_name)62940cb5e5dSvi117747 _sip_add_header(_sip_msg_t *sip_msg, _sip_header_t *new_header,
63040cb5e5dSvi117747 boolean_t append, boolean_t first, char *header_name)
63140cb5e5dSvi117747 {
63240cb5e5dSvi117747 _sip_header_t *header = NULL;
63340cb5e5dSvi117747
63440cb5e5dSvi117747 if (sip_msg == NULL || new_header == NULL)
63540cb5e5dSvi117747 return;
63640cb5e5dSvi117747 #ifdef __solaris__
63740cb5e5dSvi117747 assert(mutex_held(&sip_msg->sip_msg_mutex));
63840cb5e5dSvi117747 #endif
63940cb5e5dSvi117747 new_header->sip_hdr_sipmsg = sip_msg;
64040cb5e5dSvi117747 if (header_name != NULL) {
64140cb5e5dSvi117747 _sip_header_t *header_tmp;
64240cb5e5dSvi117747
64340cb5e5dSvi117747 header = sip_search_for_header(sip_msg, header_name, NULL);
64440cb5e5dSvi117747 header_tmp = header;
64540cb5e5dSvi117747 if (!first) {
64640cb5e5dSvi117747 while (header != NULL) {
64740cb5e5dSvi117747 header_tmp = header;
64840cb5e5dSvi117747 header = sip_search_for_header(sip_msg,
64940cb5e5dSvi117747 header_name, header);
65040cb5e5dSvi117747 }
65140cb5e5dSvi117747 }
65240cb5e5dSvi117747 header = header_tmp;
65340cb5e5dSvi117747 if (header == NULL)
65440cb5e5dSvi117747 append = B_TRUE;
65540cb5e5dSvi117747 }
65640cb5e5dSvi117747
65740cb5e5dSvi117747 if (header != NULL) {
65840cb5e5dSvi117747 if (append) {
65940cb5e5dSvi117747 new_header->sip_hdr_prev = header;
66040cb5e5dSvi117747 if (sip_msg->sip_msg_headers_end == header) {
66140cb5e5dSvi117747 sip_msg->sip_msg_headers_end = new_header;
66240cb5e5dSvi117747 new_header->sip_hdr_next = NULL;
66340cb5e5dSvi117747 } else {
66440cb5e5dSvi117747 header->sip_hdr_next->sip_hdr_prev = new_header;
66540cb5e5dSvi117747 new_header->sip_hdr_next = header->sip_hdr_next;
66640cb5e5dSvi117747 }
66740cb5e5dSvi117747 header->sip_hdr_next = new_header;
66840cb5e5dSvi117747 } else {
66940cb5e5dSvi117747 new_header->sip_hdr_next = header;
67040cb5e5dSvi117747 if (sip_msg->sip_msg_headers_start == header) {
67140cb5e5dSvi117747 sip_msg->sip_msg_headers_start = new_header;
67240cb5e5dSvi117747 new_header->sip_hdr_prev = NULL;
67340cb5e5dSvi117747 } else {
67440cb5e5dSvi117747 header->sip_hdr_prev->sip_hdr_next = new_header;
67540cb5e5dSvi117747 new_header->sip_hdr_prev = header->sip_hdr_prev;
67640cb5e5dSvi117747 }
67740cb5e5dSvi117747 header->sip_hdr_prev = new_header;
67840cb5e5dSvi117747 }
67940cb5e5dSvi117747 } else {
68040cb5e5dSvi117747 if (append) {
68140cb5e5dSvi117747 if (sip_msg->sip_msg_headers_end != NULL) {
68240cb5e5dSvi117747 sip_msg->sip_msg_headers_end->sip_hdr_next =
68340cb5e5dSvi117747 new_header;
68440cb5e5dSvi117747 } else {
68540cb5e5dSvi117747 sip_msg->sip_msg_headers_start = new_header;
68640cb5e5dSvi117747 }
68740cb5e5dSvi117747 new_header->sip_hdr_prev =
68840cb5e5dSvi117747 sip_msg->sip_msg_headers_end;
68940cb5e5dSvi117747 new_header->sip_hdr_next = NULL;
69040cb5e5dSvi117747 sip_msg->sip_msg_headers_end = new_header;
69140cb5e5dSvi117747 } else {
69240cb5e5dSvi117747 if (sip_msg->sip_msg_headers_start != NULL) {
69340cb5e5dSvi117747 sip_msg->sip_msg_headers_start->sip_hdr_prev =
69440cb5e5dSvi117747 new_header;
69540cb5e5dSvi117747 } else {
69640cb5e5dSvi117747 sip_msg->sip_msg_headers_end = new_header;
69740cb5e5dSvi117747 }
69840cb5e5dSvi117747 new_header->sip_hdr_next =
69940cb5e5dSvi117747 sip_msg->sip_msg_headers_start;
70040cb5e5dSvi117747 new_header->sip_hdr_prev = NULL;
70140cb5e5dSvi117747 sip_msg->sip_msg_headers_start = new_header;
70240cb5e5dSvi117747 }
70340cb5e5dSvi117747 }
70440cb5e5dSvi117747 sip_msg->sip_msg_len += new_header->sip_hdr_end -
70540cb5e5dSvi117747 new_header->sip_hdr_start;
70640cb5e5dSvi117747 }
70740cb5e5dSvi117747
70840cb5e5dSvi117747 /*
70940cb5e5dSvi117747 * Scan through the function table and return the entry for the given header
71040cb5e5dSvi117747 * type.
71140cb5e5dSvi117747 */
71240cb5e5dSvi117747 sip_header_function_t *
_sip_get_header_functions(sip_header_function_t * sip_header_function_table,_sip_header_t * sip_header,char * header_name)71340cb5e5dSvi117747 _sip_get_header_functions(sip_header_function_t *sip_header_function_table,
71440cb5e5dSvi117747 _sip_header_t *sip_header, char *header_name)
71540cb5e5dSvi117747 {
71640cb5e5dSvi117747 int len;
71740cb5e5dSvi117747 int i = 0;
71840cb5e5dSvi117747
71940cb5e5dSvi117747 if (sip_header == NULL && header_name == NULL)
72040cb5e5dSvi117747 return (NULL);
72140cb5e5dSvi117747
72240cb5e5dSvi117747 /*
72340cb5e5dSvi117747 * If header_name is NULL we first have to locate the name
72440cb5e5dSvi117747 */
72540cb5e5dSvi117747 if (header_name == NULL) {
72640cb5e5dSvi117747 if (sip_skip_white_space(sip_header) != 0) {
72740cb5e5dSvi117747 return (NULL);
72840cb5e5dSvi117747 }
72940cb5e5dSvi117747 header_name = sip_header->sip_hdr_current;
73040cb5e5dSvi117747 if (sip_find_separator(sip_header, SIP_HCOLON, (char)NULL,
731*df4705eaSgm209912 (char)NULL, B_FALSE) != 0) {
73240cb5e5dSvi117747 return (NULL);
73340cb5e5dSvi117747 }
73440cb5e5dSvi117747 len = sip_header->sip_hdr_current - header_name;
73540cb5e5dSvi117747 } else {
73640cb5e5dSvi117747 len = strlen(header_name);
73740cb5e5dSvi117747 }
73840cb5e5dSvi117747
73940cb5e5dSvi117747 if (len > 0) {
74040cb5e5dSvi117747 while (sip_header_function_table[i].header_name != NULL ||
74140cb5e5dSvi117747 sip_header_function_table[i].header_short_name != NULL) {
74240cb5e5dSvi117747 if (sip_header_function_table[i].header_name != NULL &&
74340cb5e5dSvi117747 len ==
74440cb5e5dSvi117747 strlen(sip_header_function_table[i].header_name)) {
74540cb5e5dSvi117747 if (strncasecmp(header_name,
74640cb5e5dSvi117747 sip_header_function_table[i].
74740cb5e5dSvi117747 header_name, len) == 0) {
74840cb5e5dSvi117747 break;
74940cb5e5dSvi117747 }
75040cb5e5dSvi117747 } else if (sip_header_function_table[i].
75140cb5e5dSvi117747 header_short_name != NULL && len ==
75240cb5e5dSvi117747 strlen(sip_header_function_table[i].
75340cb5e5dSvi117747 header_short_name)) {
75440cb5e5dSvi117747 if (strncasecmp(header_name,
75540cb5e5dSvi117747 sip_header_function_table[i].
75640cb5e5dSvi117747 header_short_name, len) == 0) {
75740cb5e5dSvi117747 break;
75840cb5e5dSvi117747 }
75940cb5e5dSvi117747 }
76040cb5e5dSvi117747 i++;
76140cb5e5dSvi117747 }
76240cb5e5dSvi117747 }
76340cb5e5dSvi117747
76440cb5e5dSvi117747 if (sip_header != NULL)
76540cb5e5dSvi117747 sip_header->sip_hdr_current = sip_header->sip_hdr_start;
76640cb5e5dSvi117747 if (sip_header_function_table[i].header_name == NULL)
76740cb5e5dSvi117747 return (NULL);
76840cb5e5dSvi117747 return (&sip_header_function_table[i]);
76940cb5e5dSvi117747 }
77040cb5e5dSvi117747
77140cb5e5dSvi117747 /*
77240cb5e5dSvi117747 * Return the entry from the function table for the given header
77340cb5e5dSvi117747 */
77440cb5e5dSvi117747 sip_header_function_t *
sip_get_header_functions(_sip_header_t * sip_header,char * header_name)77540cb5e5dSvi117747 sip_get_header_functions(_sip_header_t *sip_header, char *header_name)
77640cb5e5dSvi117747 {
77740cb5e5dSvi117747 sip_header_function_t *func;
77840cb5e5dSvi117747 sip_header_function_t *header_f_table = NULL;
77940cb5e5dSvi117747
78040cb5e5dSvi117747 if (sip_header_function_table_external != NULL) {
78140cb5e5dSvi117747 header_f_table = _sip_get_header_functions(
78240cb5e5dSvi117747 sip_header_function_table_external,
78340cb5e5dSvi117747 sip_header, header_name);
78440cb5e5dSvi117747 if (header_f_table != NULL)
78540cb5e5dSvi117747 return (header_f_table);
78640cb5e5dSvi117747 }
78740cb5e5dSvi117747 func = _sip_get_header_functions(sip_header_function_table, sip_header,
78840cb5e5dSvi117747 header_name);
78940cb5e5dSvi117747 return (func);
79040cb5e5dSvi117747 }
79140cb5e5dSvi117747
79240cb5e5dSvi117747 /*
79340cb5e5dSvi117747 * Search for the header name passed in.
79440cb5e5dSvi117747 */
79540cb5e5dSvi117747 _sip_header_t *
sip_search_for_header(_sip_msg_t * sip_msg,char * header_name,_sip_header_t * old_header)79640cb5e5dSvi117747 sip_search_for_header(_sip_msg_t *sip_msg, char *header_name,
79740cb5e5dSvi117747 _sip_header_t *old_header)
79840cb5e5dSvi117747 {
79940cb5e5dSvi117747 int len = 0;
80040cb5e5dSvi117747 int full_len = 0;
80140cb5e5dSvi117747 int compact_len = 0;
80240cb5e5dSvi117747 _sip_header_t *header = NULL;
80340cb5e5dSvi117747 char *compact_name = NULL;
80440cb5e5dSvi117747 char *full_name = NULL;
80540cb5e5dSvi117747 sip_header_function_t *header_f_table = NULL;
80640cb5e5dSvi117747
80740cb5e5dSvi117747 if (sip_msg == NULL)
80840cb5e5dSvi117747 return (NULL);
80940cb5e5dSvi117747 #ifdef __solaris__
81040cb5e5dSvi117747 assert(mutex_held(&sip_msg->sip_msg_mutex));
81140cb5e5dSvi117747 #endif
81240cb5e5dSvi117747
81340cb5e5dSvi117747 if (header_name != NULL) {
81440cb5e5dSvi117747 header_f_table = sip_get_header_functions(NULL, header_name);
81540cb5e5dSvi117747 if (header_f_table != NULL) {
81640cb5e5dSvi117747 full_name = header_f_table->header_name;
81740cb5e5dSvi117747 compact_name = header_f_table->header_short_name;
81840cb5e5dSvi117747 if (full_name != NULL)
81940cb5e5dSvi117747 full_len = strlen(full_name);
82040cb5e5dSvi117747 if (compact_name != NULL)
82140cb5e5dSvi117747 compact_len = strlen(compact_name);
82240cb5e5dSvi117747 } else {
82340cb5e5dSvi117747 header_f_table = &sip_header_function_table[0];
82440cb5e5dSvi117747 full_name = header_name;
82540cb5e5dSvi117747 full_len = strlen(full_name);
82640cb5e5dSvi117747 }
82740cb5e5dSvi117747 }
82840cb5e5dSvi117747
82940cb5e5dSvi117747 if (old_header != NULL)
83040cb5e5dSvi117747 header = old_header->sip_hdr_next;
83140cb5e5dSvi117747 else
83240cb5e5dSvi117747 header = sip_msg->sip_msg_headers_start;
83340cb5e5dSvi117747
83440cb5e5dSvi117747 while (header != NULL) {
83540cb5e5dSvi117747
83640cb5e5dSvi117747 if (header->sip_header_state == SIP_HEADER_DELETED) {
83740cb5e5dSvi117747 header = header->sip_hdr_next;
83840cb5e5dSvi117747 continue;
83940cb5e5dSvi117747 }
84040cb5e5dSvi117747
84140cb5e5dSvi117747 if (compact_len == 0 && full_len == 0)
84240cb5e5dSvi117747 break;
84340cb5e5dSvi117747
84440cb5e5dSvi117747 header->sip_hdr_current = header->sip_hdr_start;
84540cb5e5dSvi117747
84640cb5e5dSvi117747 if (sip_skip_white_space(header)) {
84740cb5e5dSvi117747 header = header->sip_hdr_next;
84840cb5e5dSvi117747 continue;
84940cb5e5dSvi117747 }
85040cb5e5dSvi117747
85140cb5e5dSvi117747 len = header->sip_hdr_end - header->sip_hdr_current;
85240cb5e5dSvi117747
85340cb5e5dSvi117747 if (full_name != NULL && (full_len <= len) &&
85440cb5e5dSvi117747 strncasecmp(header->sip_hdr_current, full_name,
85540cb5e5dSvi117747 full_len) == 0) {
85640cb5e5dSvi117747 header->sip_hdr_current += full_len;
85740cb5e5dSvi117747 if (sip_skip_white_space(header)) {
85840cb5e5dSvi117747 header = header->sip_hdr_next;
85940cb5e5dSvi117747 continue;
86040cb5e5dSvi117747 }
86140cb5e5dSvi117747
86240cb5e5dSvi117747 if (*header->sip_hdr_current == SIP_HCOLON) {
86340cb5e5dSvi117747 header_name = full_name;
86440cb5e5dSvi117747 break;
86540cb5e5dSvi117747 }
86640cb5e5dSvi117747 }
86740cb5e5dSvi117747
86840cb5e5dSvi117747 if (compact_name != NULL && (compact_len <= len) &&
86940cb5e5dSvi117747 strncasecmp(header->sip_hdr_current, compact_name,
87040cb5e5dSvi117747 compact_len) == 0) {
87140cb5e5dSvi117747 header->sip_hdr_current += compact_len;
87240cb5e5dSvi117747 if (sip_skip_white_space(header)) {
87340cb5e5dSvi117747 header = header->sip_hdr_next;
87440cb5e5dSvi117747 continue;
87540cb5e5dSvi117747 }
87640cb5e5dSvi117747 if (*header->sip_hdr_current == SIP_HCOLON) {
87740cb5e5dSvi117747 header_name = compact_name;
87840cb5e5dSvi117747 break;
87940cb5e5dSvi117747 }
88040cb5e5dSvi117747 }
88140cb5e5dSvi117747 header = header->sip_hdr_next;
88240cb5e5dSvi117747 }
88340cb5e5dSvi117747
88440cb5e5dSvi117747 if (header != NULL) {
88540cb5e5dSvi117747 header->sip_hdr_current = header->sip_hdr_start;
88640cb5e5dSvi117747 if (header_f_table == NULL) {
88740cb5e5dSvi117747 header_f_table =
88840cb5e5dSvi117747 sip_get_header_functions(header, header_name);
88940cb5e5dSvi117747 if (header_f_table == NULL)
89040cb5e5dSvi117747 header_f_table = &sip_header_function_table[0];
89140cb5e5dSvi117747 }
89240cb5e5dSvi117747
89340cb5e5dSvi117747 header->sip_header_functions = header_f_table;
89440cb5e5dSvi117747 }
89540cb5e5dSvi117747 return (header);
89640cb5e5dSvi117747 }
89740cb5e5dSvi117747
89840cb5e5dSvi117747 /*
89940cb5e5dSvi117747 * Return the start line as a string. Caller frees string
90040cb5e5dSvi117747 */
90140cb5e5dSvi117747 char *
_sip_startline_to_str(_sip_msg_t * sip_msg,int * error)90240cb5e5dSvi117747 _sip_startline_to_str(_sip_msg_t *sip_msg, int *error)
90340cb5e5dSvi117747 {
90440cb5e5dSvi117747 char *slstr;
90540cb5e5dSvi117747 int len;
90640cb5e5dSvi117747
90740cb5e5dSvi117747 if (error != NULL)
90840cb5e5dSvi117747 *error = 0;
90940cb5e5dSvi117747
91040cb5e5dSvi117747 if (sip_msg == NULL || sip_msg->sip_msg_start_line == NULL) {
91140cb5e5dSvi117747 if (error != NULL)
91240cb5e5dSvi117747 *error = EINVAL;
91340cb5e5dSvi117747 return (NULL);
91440cb5e5dSvi117747 }
91540cb5e5dSvi117747 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
91640cb5e5dSvi117747 len = sip_msg->sip_msg_start_line->sip_hdr_end -
91740cb5e5dSvi117747 sip_msg->sip_msg_start_line->sip_hdr_start - 2;
91840cb5e5dSvi117747 if ((slstr = malloc(len + 1)) == NULL) {
91940cb5e5dSvi117747 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
92040cb5e5dSvi117747 if (error != NULL)
92140cb5e5dSvi117747 *error = ENOMEM;
92240cb5e5dSvi117747 return (NULL);
92340cb5e5dSvi117747 }
92440cb5e5dSvi117747 (void) strncpy(slstr, sip_msg->sip_msg_start_line->sip_hdr_start, len);
92540cb5e5dSvi117747 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
92640cb5e5dSvi117747 slstr[len] = '\0';
92740cb5e5dSvi117747 return (slstr);
92840cb5e5dSvi117747 }
92940cb5e5dSvi117747
93040cb5e5dSvi117747 /*
93140cb5e5dSvi117747 * Return the given header as a string. Caller frees string
93240cb5e5dSvi117747 */
93340cb5e5dSvi117747 char *
sip_hdr_to_str(sip_header_t sip_header,int * error)93440cb5e5dSvi117747 sip_hdr_to_str(sip_header_t sip_header, int *error)
93540cb5e5dSvi117747 {
93640cb5e5dSvi117747 char *hdrstr;
93740cb5e5dSvi117747 char *tmpptr;
93840cb5e5dSvi117747 _sip_header_t *_sip_header;
93940cb5e5dSvi117747 int len;
94040cb5e5dSvi117747
94140cb5e5dSvi117747 if (error != NULL)
94240cb5e5dSvi117747 *error = 0;
94340cb5e5dSvi117747
94440cb5e5dSvi117747 if (sip_header == NULL) {
94540cb5e5dSvi117747 if (error != NULL)
94640cb5e5dSvi117747 *error = EINVAL;
94740cb5e5dSvi117747 return (NULL);
94840cb5e5dSvi117747 }
94940cb5e5dSvi117747 _sip_header = (_sip_header_t *)sip_header;
95040cb5e5dSvi117747 if (_sip_header->sip_header_state == SIP_HEADER_DELETED) {
95140cb5e5dSvi117747 if (_sip_header->sip_hdr_sipmsg != NULL) {
95240cb5e5dSvi117747 (void) pthread_mutex_unlock(
95340cb5e5dSvi117747 &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
95440cb5e5dSvi117747 }
95540cb5e5dSvi117747 if (error != NULL)
95640cb5e5dSvi117747 *error = EINVAL;
95740cb5e5dSvi117747 return (NULL);
95840cb5e5dSvi117747 }
95940cb5e5dSvi117747 if (_sip_header->sip_hdr_sipmsg != NULL) {
96040cb5e5dSvi117747 (void) pthread_mutex_lock(
96140cb5e5dSvi117747 &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
96240cb5e5dSvi117747 }
96340cb5e5dSvi117747 len = _sip_header->sip_hdr_end - _sip_header->sip_hdr_start;
96440cb5e5dSvi117747 hdrstr = malloc(len);
96540cb5e5dSvi117747 if (hdrstr == NULL) {
96640cb5e5dSvi117747 if (_sip_header->sip_hdr_sipmsg != NULL) {
96740cb5e5dSvi117747 (void) pthread_mutex_unlock(
96840cb5e5dSvi117747 &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
96940cb5e5dSvi117747 }
97040cb5e5dSvi117747 if (error != NULL)
97140cb5e5dSvi117747 *error = ENOMEM;
97240cb5e5dSvi117747 return (NULL);
97340cb5e5dSvi117747 }
97440cb5e5dSvi117747 if (_sip_header->sip_header_state == SIP_HEADER_DELETED_VAL) {
97540cb5e5dSvi117747 len = sip_copy_values(hdrstr, _sip_header);
97640cb5e5dSvi117747 } else {
97740cb5e5dSvi117747 (void) strncpy(hdrstr, _sip_header->sip_hdr_start, len);
97840cb5e5dSvi117747 }
97940cb5e5dSvi117747 if (_sip_header->sip_hdr_sipmsg != NULL) {
98040cb5e5dSvi117747 (void) pthread_mutex_unlock(
98140cb5e5dSvi117747 &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
98240cb5e5dSvi117747 }
98340cb5e5dSvi117747 tmpptr = hdrstr + len;
98440cb5e5dSvi117747 while (*tmpptr-- != '\n') {
98540cb5e5dSvi117747 if (tmpptr == _sip_header->sip_hdr_start) {
98640cb5e5dSvi117747 free(hdrstr);
98740cb5e5dSvi117747 if (error != NULL)
98840cb5e5dSvi117747 *error = EINVAL;
98940cb5e5dSvi117747 return (NULL);
99040cb5e5dSvi117747 }
99140cb5e5dSvi117747 }
99240cb5e5dSvi117747 *tmpptr = '\0';
99340cb5e5dSvi117747 return (hdrstr);
99440cb5e5dSvi117747 }
99540cb5e5dSvi117747
99640cb5e5dSvi117747 /*
99740cb5e5dSvi117747 * Given a param list find the named parameter.
99840cb5e5dSvi117747 * Returns a pointer to the value or NULL.
99940cb5e5dSvi117747 */
100040cb5e5dSvi117747 sip_param_t *
sip_get_param_from_list(sip_param_t * param_list,char * param_name)100140cb5e5dSvi117747 sip_get_param_from_list(sip_param_t *param_list, char *param_name)
100240cb5e5dSvi117747 {
100340cb5e5dSvi117747 while (param_list != NULL) {
100440cb5e5dSvi117747 if (param_list->param_name.sip_str_len == strlen(param_name) &&
100540cb5e5dSvi117747 strncasecmp(param_list->param_name.sip_str_ptr, param_name,
100640cb5e5dSvi117747 strlen(param_name)) == 0) {
100740cb5e5dSvi117747 return (param_list);
100840cb5e5dSvi117747 }
100940cb5e5dSvi117747 param_list = param_list->param_next;
101040cb5e5dSvi117747 }
101140cb5e5dSvi117747 return (NULL);
101240cb5e5dSvi117747 }
1013