40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * CDDL HEADER START
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * The contents of this file are subject to the terms of the
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Common Development and Distribution License (the "License").
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * You may not use this file except in compliance with the License.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * See the License for the specific language governing permissions
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * and limitations under the License.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * When distributing Covered Code, include this CDDL HEADER in each
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * If applicable, add the following below this CDDL HEADER, with the
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * fields enclosed by brackets "[]" replaced with your own identifying
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * information: Portions Copyright [yyyy] [name of copyright owner]
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * CDDL HEADER END
2c2c41837e330b002c4220a39638150db504fe0evi * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Use is subject to license terms.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi#pragma ident "%Z%%M% %I% %E% SMI"
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * atoi function from a header
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi while (sip_header->sip_hdr_current < sip_header->sip_hdr_end) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Find the 'token'
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi while (sip_header->sip_hdr_current < sip_header->sip_hdr_end) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (1);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * sip_hdr_current points to the char
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * after the token
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (1);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Find a carriage-return
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_header->sip_hdr_current == sip_header->sip_hdr_start)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (1);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Find one of the separator provided, i.e. separator_1st or separator_2nd or
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * separator_3rd.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_find_separator(_sip_header_t *sip_header, char separator_1st,
df4705eab9c873eae60bada4f2138e6f22a76e11gm char separator_2nd, char separator_3rd, boolean_t ignore_space)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi assert(separator_1st != (char)NULL || separator_2nd != (char)NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi while (sip_header->sip_hdr_current < sip_header->sip_hdr_end) {
df4705eab9c873eae60bada4f2138e6f22a76e11gm if (ignore_space && (*sip_header->sip_hdr_current == SIP_SP)) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * If we have escape character, go to the next char
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (1);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Return when we hit a white space
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi while (sip_header->sip_hdr_current < sip_header->sip_hdr_end) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (1);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Skip to the next non-whitespace
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi while (sip_header->sip_hdr_current < sip_header->sip_hdr_end) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (1);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Skip to the non-white space in the reverse direction
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi while (sip_header->sip_hdr_current >= sip_header->sip_hdr_start) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (1);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * get to the first non space after ':'
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (1);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (1);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Skip the current value.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi while (sip_header->sip_hdr_current < sip_header->sip_hdr_end) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi } else if (!quoted &&
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * value ends before the COMMA
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (1);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Parse the header into parameter list. Parameters start with a ';'
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_parse_params(_sip_header_t *sip_header, sip_param_t **parsed_list)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi for (;;) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * First check if there are any params
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Let's get to the start of the param name
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * start of param name
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * End of param name
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * We are at EQUAL, lets go beyond that
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * start of param value
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi param->param_value.sip_str_ptr = sip_header->sip_hdr_current;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (quoted_name && sip_find_token(sip_header, SIP_QUOTE) != 0) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi } else if (sip_find_separator(sip_header, SIP_SEMI, SIP_COMMA,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi param->param_value.sip_str_len = sip_header->sip_hdr_current -
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * a header that only has "header_name : " is an empty header
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * ":" must exist
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * sip_hdr_current resets to sip_hdr_start before exit
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Parsing an empty header, i.e. only has a ":"
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_parse_hdr_empty(_sip_header_t *hdr, sip_parsed_header_t **phdr)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * check if already parsed
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * validate uri str and parse uri using uri_parse()
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vistatic void
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_parse_uri_str(sip_str_t *sip_str, sip_hdr_value_t *value)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Parse uri
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi value->sip_value_parsed_uri = sip_parse_uri(sip_str, &error);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (error != 0 ||
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Some basic common checks before parsing the headers
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_prim_parsers(_sip_header_t *sip_header, sip_parsed_header_t **header)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * check if already parsed
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi assert(sip_header->sip_hdr_start == sip_header->sip_hdr_current);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Parse SIP/2.0 string
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (1);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (strncasecmp(sip_header->sip_hdr_current, SIP, strlen(SIP)) == 0) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (1);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (1);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (1);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (1);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (1);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (1);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (1);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * parser1 parses hdr format
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * header_name: val1[; par1=pval1;par2=pval2 ..][, val2[;parlist..] ]
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * val can be str1/str2 or str
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * headers: Accept, Accept-Encode, Accept-lang, Allow, Content-disp,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Content-Encode, Content-Lang, In-reply-to,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Priority, Require, Supported, Unsupported
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Allow-Events, Event, Subscription-State
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_parse_hdr_parser1(_sip_header_t *hdr, sip_parsed_header_t **phdr, char sep)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * check if previously parsed
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * nothing at the end except space
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * white space skipped
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * only one string until COMMA, use sip_str_t
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (c == SIP_COMMA) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * two strings, use sip_2strs_t
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * if COMMA, no param list, get next val
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * if SEMI, need to set params list
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi } else { /* the last part */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * c == SEMI, value contains single string
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * only one string until SEMI, use sip_str_t
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (c == SIP_SEMI) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * get rid of SP at end of value field
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * if SEMI exists in the value, set params list
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * two situations, there is or not SLASH before SEMI
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi } else if (ret != 0) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * header_name: int
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * headers: Expires, Min-Expires
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/* ARGSUSED */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_parse_hdr_parser2(_sip_header_t *hdr, sip_parsed_header_t **phdr,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * check if previously parsed
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (ret != 0) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * parser3 parses hdr format
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * header_name: <val1>[, <val2>]
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Alert-Info, Call-Info, Error-Info, reply-to
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_parse_hdr_parser3(_sip_header_t *hdr, sip_parsed_header_t **phdr, int type,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * check if previously parsed
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * record the position after LAQUOT
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * get display name and store in str1
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * record start pos of display name
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * set current to the char after LAQUOT
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * no RAQUOT
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * No display name - Only URI.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * alert-info, error-info, call-info
df4705eab9c873eae60bada4f2138e6f22a76e11gm r = sip_find_separator(hdr, SIP_COMMA, SIP_SEMI, (char)NULL,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (r != 0) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * parser4 parses hdr format, the whole field is one single str
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * header: Subject, MIME-Version, Organization, Server, User-Agent
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_parse_hdr_parser4(_sip_header_t *hdr, sip_parsed_header_t **phdr)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * check if previously parsed
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * get rid of CRLF at end
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi value->str_val_len = hdr->sip_hdr_end - value->str_val_ptr - 2;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_parse_hdr_parser5(_sip_header_t *hdr, sip_parsed_header_t **phdr,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * check if previously parsed
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * get auth_scheme
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi value->auth_scheme_len = hdr->sip_hdr_current - value->auth_scheme_ptr;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * parse auth_param
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi for (;;) {
df4705eab9c873eae60bada4f2138e6f22a76e11gm if (sip_find_separator(hdr, SIP_EQUAL, SIP_COMMA, (char)NULL,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * End of param name
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi tmp_param->param_name.sip_str_len = hdr->sip_hdr_current -
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * We are at EQUAL
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * start of param value
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Parse uri
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Return the URI in the request startline
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi_sip_get_request_uri(_sip_header_t *sip_header, sip_message_type_t *msg_info)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_header->sip_hdr_current >= sip_header->sip_hdr_end)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi msg_info->U.sip_request.sip_request_uri.sip_str_ptr = start_ptr;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi msg_info->U.sip_request.sip_request_uri.sip_str_len = size;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Parse the start line into request/response
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_parse_first_line(_sip_header_t *sip_header, sip_message_type_t **msg_info)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * There is nothing, return
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi assert(mutex_held(&sip_header->sip_hdr_sipmsg->sip_msg_mutex));
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * let's see if it's a request or a response
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (ret == 0) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * check for status code.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_header->sip_hdr_current + SIP_SIZE_OF_STATUS_CODE >=
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_msg_info->U.sip_response.sip_response_code < 100 ||
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * get reason phrase.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * It's a request.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Get SIP version
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (ret != 0) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);