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 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 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 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 * 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 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 * 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 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 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 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 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 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 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 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 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 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 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 * 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 * 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 * 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 * 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 * 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 * 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