#include <ctype.h>
#include <errno.h>
#include <stdlib.h>
#include <strings.h>
#include <sip.h>
#include "sip_msg.h"
#include "sip_miscdefs.h"
#include "sip_parse_generic.h"
#include "sip_parse_uri.h"
int
sip_parse_acpt_header(_sip_header_t *sip_header, sip_parsed_header_t **header)
{
if (sip_is_empty_hdr(sip_header))
return (sip_parse_hdr_empty(sip_header, header));
return (sip_parse_hdr_parser1(sip_header, header, SIP_SLASH));
}
int
sip_parse_acpt_encode_header(_sip_header_t *sip_header,
sip_parsed_header_t **header)
{
return (sip_parse_hdr_parser1(sip_header, header, 0));
}
int
sip_parse_acpt_lang_header(_sip_header_t *sip_header,
sip_parsed_header_t **header)
{
if (sip_is_empty_hdr(sip_header))
return (sip_parse_hdr_empty(sip_header, header));
return (sip_parse_hdr_parser1(sip_header, header, 0));
}
int
sip_parse_alert_header(_sip_header_t *sip_header, sip_parsed_header_t **header)
{
return (sip_parse_hdr_parser3(sip_header, header, SIP_STR_VAL, B_TRUE));
}
int
sip_parse_allow_header(_sip_header_t *hdr, sip_parsed_header_t **phdr)
{
sip_parsed_header_t *parsed_header;
sip_hdr_value_t *value = NULL;
sip_hdr_value_t *last_value = NULL;
int len;
int i;
int ret;
boolean_t multi_value = B_FALSE;
if ((ret = sip_prim_parsers(hdr, phdr)) != 0)
return (ret);
if (*phdr != NULL)
return (0);
parsed_header = calloc(1, sizeof (sip_parsed_header_t));
if (parsed_header == NULL)
return (ENOMEM);
parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1;
parsed_header->sip_header = hdr;
while (hdr->sip_hdr_current < hdr->sip_hdr_end) {
value = calloc(1, sizeof (sip_hdr_value_t));
if (value == NULL) {
sip_free_phdr(parsed_header);
return (ENOMEM);
}
if (last_value != NULL)
last_value->sip_next_value = value;
else
parsed_header->value = (sip_value_t *)value;
value->sip_value_start = hdr->sip_hdr_current;
value->sip_value_header = parsed_header;
if (sip_find_separator(hdr, SIP_COMMA, 0, 0, B_FALSE) == 0) {
multi_value = B_TRUE;
}
len = hdr->sip_hdr_current - value->sip_value_start;
for (i = 1; i < MAX_SIP_METHODS; i++) {
if (strncmp(sip_methods[i].name, value->sip_value_start,
len) == 0) {
break;
}
}
if (i >= MAX_SIP_METHODS) {
value->int_val = 0;
value->sip_value_state = SIP_VALUE_BAD;
if (multi_value)
goto next_val;
else
goto end;
}
value->int_val = i;
if (!multi_value)
goto end;
next_val:
if (sip_find_token(hdr, SIP_COMMA) != 0)
break;
value->sip_value_end = hdr->sip_hdr_current - 1;
last_value = value;
(void) sip_skip_white_space(hdr);
}
end:
*phdr = parsed_header;
return (0);
}
int
sip_parse_callinfo_header(_sip_header_t *sip_header,
sip_parsed_header_t **header)
{
return (sip_parse_hdr_parser3(sip_header, header, SIP_STR_VAL, B_TRUE));
}
int
sip_parse_contentdis_header(_sip_header_t *sip_header,
sip_parsed_header_t **header)
{
return (sip_parse_hdr_parser1(sip_header, header, 0));
}
int
sip_parse_contentencode_header(_sip_header_t *sip_header,
sip_parsed_header_t **header)
{
return (sip_parse_hdr_parser1(sip_header, header, 0));
}
int
sip_parse_contentlang_header(_sip_header_t *sip_header,
sip_parsed_header_t **header)
{
return (sip_parse_hdr_parser1(sip_header, header, 0));
}
int
sip_parse_date_header(_sip_header_t *sip_header, sip_parsed_header_t **header)
{
sip_parsed_header_t *parsed_header;
int r;
sip_hdr_value_t *value = NULL;
if ((r = sip_prim_parsers(sip_header, header)) != 0)
return (r);
if (*header != NULL)
return (0);
parsed_header = calloc(1, sizeof (sip_parsed_header_t));
if (parsed_header == NULL)
return (ENOMEM);
parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1;
parsed_header->sip_header = sip_header;
value = calloc(1, sizeof (sip_hdr_value_t));
if (value == NULL) {
sip_free_phdr(parsed_header);
return (ENOMEM);
}
parsed_header->value = (sip_value_t *)value;
value->sip_value_start = sip_header->sip_hdr_current;
value->sip_value_header = parsed_header;
value->date_wd_ptr = sip_header->sip_hdr_current;
if (sip_find_token(sip_header, SIP_COMMA) == 0) {
value->date_wd_len = sip_header->sip_hdr_current -
value->date_wd_ptr - 1;
sip_header->sip_hdr_current++;
if (sip_skip_white_space(sip_header) != 0) {
value->sip_value_state = SIP_VALUE_BAD;
return (EPROTO);
}
} else {
value->sip_value_state = SIP_VALUE_BAD;
return (EPROTO);
}
if (sip_skip_white_space(sip_header) != 0) {
value->sip_value_state = SIP_VALUE_BAD;
return (EPROTO);
}
r = sip_atoi(sip_header, &value->date_d);
if (r != 0 || value->date_d < 0 || value->date_d > 31) {
value->sip_value_state = SIP_VALUE_BAD;
return (EPROTO);
}
if (sip_skip_white_space(sip_header) != 0) {
value->sip_value_state = SIP_VALUE_BAD;
return (EPROTO);
}
value->date_m_ptr = sip_header->sip_hdr_current;
if (sip_find_token(sip_header, SIP_SP) == 0) {
value->date_m_len = sip_header->sip_hdr_current -
value->date_m_ptr - 1;
} else {
value->sip_value_state = SIP_VALUE_BAD;
return (EPROTO);
}
r = sip_atoi(sip_header, &value->date_y);
if (r != 0 || value->date_y < 0) {
value->sip_value_state = SIP_VALUE_BAD;
return (EPROTO);
}
if (sip_skip_white_space(sip_header) != 0) {
value->sip_value_state = SIP_VALUE_BAD;
return (EPROTO);
}
value->date_t_ptr = sip_header->sip_hdr_current;
if (sip_find_token(sip_header, SIP_SP) == 0) {
value->date_t_len = sip_header->sip_hdr_current -
value->date_t_ptr - 1;
} else {
value->sip_value_state = SIP_VALUE_BAD;
return (EPROTO);
}
value->date_tz_ptr = sip_header->sip_hdr_current;
value->date_tz_len = sip_header->sip_hdr_end -
sip_header->sip_hdr_current - 2;
*header = parsed_header;
sip_header->sip_hdr_parsed = *header;
return (0);
}
int
sip_parse_errorinfo_header(_sip_header_t *sip_header,
sip_parsed_header_t **header)
{
return (sip_parse_hdr_parser3(sip_header, header, SIP_STR_VAL, B_TRUE));
}
int
sip_parse_expire_header(_sip_header_t *sip_header,
sip_parsed_header_t **header)
{
return (sip_parse_hdr_parser2(sip_header, header, SIP_INT_VAL));
}
int
sip_parse_inreplyto_header(_sip_header_t *sip_header,
sip_parsed_header_t **header)
{
return (sip_parse_hdr_parser1(sip_header, header, 0));
}
int
sip_parse_rseq(_sip_header_t *sip_header, sip_parsed_header_t **header)
{
int r;
sip_hdr_value_t *rseq_value;
r = sip_parse_hdr_parser2(sip_header, header, SIP_INT_VAL);
if (sip_header->sip_hdr_parsed != NULL &&
sip_header->sip_hdr_parsed->value != NULL) {
rseq_value = (sip_hdr_value_t *)
sip_header->sip_hdr_parsed->value;
if (rseq_value->int_val == 0)
rseq_value->sip_value_state = SIP_VALUE_BAD;
}
return (r);
}
int
sip_parse_minexpire_header(_sip_header_t *sip_header,
sip_parsed_header_t **header)
{
return (sip_parse_hdr_parser2(sip_header, header, SIP_INT_VAL));
}
int
sip_parse_mimeversion_header(_sip_header_t *sip_header,
sip_parsed_header_t **header)
{
return (sip_parse_hdr_parser4(sip_header, header));
}
int
sip_parse_org_header(_sip_header_t *sip_header,
sip_parsed_header_t **header)
{
if (sip_is_empty_hdr(sip_header))
return (sip_parse_hdr_empty(sip_header, header));
return (sip_parse_hdr_parser4(sip_header, header));
}
int
sip_parse_priority_header(_sip_header_t *sip_header,
sip_parsed_header_t **header)
{
return (sip_parse_hdr_parser4(sip_header, header));
}
int
sip_parse_replyto_header(_sip_header_t *sip_header,
sip_parsed_header_t **header)
{
return (sip_parse_hdr_parser3(sip_header, header, SIP_STRS_VAL,
B_TRUE));
}
int
sip_parse_privacy_header(_sip_header_t *sip_header,
sip_parsed_header_t **header)
{
return (sip_parse_hdr_parser1(sip_header, header, 0));
}
int
sip_parse_require_header(_sip_header_t *sip_header,
sip_parsed_header_t **header)
{
return (sip_parse_hdr_parser1(sip_header, header, 0));
}
int
sip_parse_retryaft_header(_sip_header_t *sip_header,
sip_parsed_header_t **header)
{
sip_parsed_header_t *parsed_header;
sip_hdr_value_t *value = NULL;
int ret;
if ((ret = sip_prim_parsers(sip_header, header)) != 0)
return (ret);
if (*header != NULL)
return (0);
parsed_header = calloc(1, sizeof (sip_parsed_header_t));
if (parsed_header == NULL)
return (ENOMEM);
parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1;
parsed_header->sip_header = sip_header;
value = calloc(1, sizeof (sip_hdr_value_t));
if (value == NULL) {
sip_free_phdr(parsed_header);
return (ENOMEM);
}
parsed_header->value = (sip_value_t *)value;
value->sip_value_start = sip_header->sip_hdr_current;
value->sip_value_header = parsed_header;
ret = sip_atoi(sip_header, &(value->intstr_int));
if (ret != 0)
value->sip_value_state = SIP_VALUE_BAD;
if (sip_find_token(sip_header, SIP_LPAR) == 0) {
value->intstr_str_ptr = sip_header->sip_hdr_current;
if (sip_find_token(sip_header, SIP_RPAR) == 0) {
value->intstr_str_len =
sip_header->sip_hdr_current -
value->intstr_str_ptr - 1;
if (sip_find_token(sip_header, SIP_SEMI) == 0) {
sip_header->sip_hdr_current--;
(void) sip_parse_params(sip_header,
&(value->sip_param_list));
}
} else {
value->sip_value_state = SIP_VALUE_BAD;
return (EPROTO);
}
} else {
value->intstr_str_ptr = NULL;
value->intstr_str_len = 0;
sip_header->sip_hdr_current = value->sip_value_start;
if (sip_find_token(sip_header, SIP_SEMI) == 0) {
sip_header->sip_hdr_current--;
(void) sip_parse_params(sip_header,
&(value->sip_param_list));
}
}
*header = parsed_header;
sip_header->sip_hdr_parsed = *header;
return (0);
}
int
sip_parse_server_header(_sip_header_t *sip_header, sip_parsed_header_t **header)
{
return (sip_parse_hdr_parser4(sip_header, header));
}
int
sip_parse_subject_header(_sip_header_t *sip_header,
sip_parsed_header_t **header)
{
if (sip_is_empty_hdr(sip_header))
return (sip_parse_hdr_empty(sip_header, header));
return (sip_parse_hdr_parser4(sip_header, header));
}
int
sip_parse_support_header(_sip_header_t *sip_header,
sip_parsed_header_t **header)
{
if (sip_is_empty_hdr(sip_header))
return (sip_parse_hdr_empty(sip_header, header));
return (sip_parse_hdr_parser1(sip_header, header, 0));
}
int
sip_parse_timestamp_header(_sip_header_t *sip_header,
sip_parsed_header_t **header)
{
sip_parsed_header_t *parsed_header;
sip_hdr_value_t *value = NULL;
int ret;
if ((ret = sip_prim_parsers(sip_header, header)) != 0)
return (ret);
if (*header != NULL)
return (0);
parsed_header = calloc(1, sizeof (sip_parsed_header_t));
if (parsed_header == NULL)
return (ENOMEM);
parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1;
parsed_header->sip_header = sip_header;
value = calloc(1, sizeof (sip_hdr_value_t));
if (value == NULL) {
sip_free_phdr(parsed_header);
return (ENOMEM);
}
parsed_header->value = (sip_value_t *)value;
value->sip_value_start = sip_header->sip_hdr_current;
value->sip_value_header = parsed_header;
if (sip_skip_white_space(sip_header) != 0) {
value->sip_value_state = SIP_VALUE_BAD;
return (EPROTO);
}
value->strs1_val_ptr = sip_header->sip_hdr_current;
if (sip_find_white_space(sip_header) == 0) {
value->strs1_val_len = sip_header->sip_hdr_current -
value->strs1_val_ptr;
(void) sip_skip_white_space(sip_header);
value->strs2_val_ptr = sip_header->sip_hdr_current;
if (sip_find_cr(sip_header) != 0) {
value->sip_value_state = SIP_VALUE_BAD;
return (EPROTO);
}
if (sip_header->sip_hdr_current < value->strs2_val_ptr) {
value->strs2_val_ptr = NULL;
value->strs2_val_len = 0;
} else {
value->strs2_val_len = sip_header->sip_hdr_current -
value->strs2_val_ptr;
}
} else {
value->strs1_val_len = sip_header->sip_hdr_current
- value->strs1_val_ptr;
value->strs2_val_ptr = NULL;
value->strs2_val_len = 0;
}
*header = parsed_header;
sip_header->sip_hdr_parsed = *header;
return (0);
}
int
sip_parse_usupport_header(_sip_header_t *sip_header,
sip_parsed_header_t **header)
{
return (sip_parse_hdr_parser1(sip_header, header, 0));
}
int
sip_parse_useragt_header(_sip_header_t *sip_header,
sip_parsed_header_t **header)
{
return (sip_parse_hdr_parser4(sip_header, header));
}
int
sip_parse_warn_header(_sip_header_t *sip_header, sip_parsed_header_t **header)
{
sip_parsed_header_t *parsed_header;
int ret;
sip_hdr_value_t *value = NULL;
sip_hdr_value_t *last_value = NULL;
if ((ret = sip_prim_parsers(sip_header, header)) != 0)
return (ret);
if (*header != NULL)
return (0);
parsed_header = calloc(1, sizeof (sip_parsed_header_t));
if (parsed_header == NULL)
return (ENOMEM);
parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1;
parsed_header->sip_header = sip_header;
while (sip_header->sip_hdr_current < sip_header->sip_hdr_end) {
value = calloc(1, sizeof (sip_hdr_value_t));
if (value == NULL) {
sip_free_phdr(parsed_header);
return (ENOMEM);
}
if (last_value != NULL)
last_value->sip_next_value = value;
else
parsed_header->value = (sip_value_t *)value;
value->sip_value_start = sip_header->sip_hdr_current;
value->sip_value_header = parsed_header;
ret = sip_atoi(sip_header, &value->warn_code);
if (ret != 0 || value->warn_code < 100 ||
value->warn_code > 999) {
value->sip_value_state = SIP_VALUE_BAD;
goto get_next_val;
}
if (sip_skip_white_space(sip_header) != 0) {
value->sip_value_state = SIP_VALUE_BAD;
goto get_next_val;
}
value->warn_agt_ptr = sip_header->sip_hdr_current;
if (sip_find_token(sip_header, SIP_QUOTE) == 0) {
sip_header->sip_hdr_current--;
(void) sip_reverse_skip_white_space(sip_header);
value->warn_agt_len = sip_header->sip_hdr_current -
value->warn_agt_ptr - 1;
if (value->warn_agt_len <= 0) {
value->warn_agt_ptr = NULL;
value->sip_value_state = SIP_VALUE_BAD;
}
(void) sip_find_token(sip_header, SIP_QUOTE);
value->warn_text_ptr = sip_header->sip_hdr_current;
if (sip_find_token(sip_header, SIP_QUOTE) == 0) {
value->warn_text_len =
sip_header->sip_hdr_current -
value->warn_text_ptr - 1;
} else {
value->sip_value_state = SIP_VALUE_BAD;
goto get_next_val;
}
} else
value->sip_value_state = SIP_VALUE_BAD;
get_next_val:
if (sip_find_token(sip_header, SIP_COMMA) != 0)
break;
value->sip_value_end = sip_header->sip_hdr_current - 1;
last_value = value;
(void) sip_skip_white_space(sip_header);
}
*header = parsed_header;
sip_header->sip_hdr_parsed = *header;
return (0);
}
int
sip_parse_rack(_sip_header_t *sip_header, sip_parsed_header_t **header)
{
sip_parsed_header_t *parsed_header;
sip_hdr_value_t *rack_value;
int len;
char *tmp_ptr;
int i;
int ret;
if ((ret = sip_prim_parsers(sip_header, header)) != 0)
return (ret);
if (*header != NULL)
return (0);
parsed_header = calloc(1, sizeof (sip_parsed_header_t));
if (parsed_header == NULL)
return (ENOMEM);
parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1;
parsed_header->sip_header = sip_header;
parsed_header->value = calloc(1, sizeof (sip_hdr_value_t));
if (parsed_header->value == NULL) {
free(parsed_header);
return (ENOMEM);
}
rack_value = (sip_hdr_value_t *)parsed_header->value;
rack_value->sip_value_version = SIP_VALUE_VERSION_1;
rack_value->sip_value_start = sip_header->sip_hdr_current;
rack_value->sip_value_header = parsed_header;
if (sip_atoi(sip_header, &rack_value->rack_resp) ||
rack_value->rack_resp == 0) {
rack_value->sip_value_state = SIP_VALUE_BAD;
rack_value->sip_value_end = sip_header->sip_hdr_end - 2;
goto rack_parse_done;
}
rack_value->sip_value_header = parsed_header;
if (sip_skip_white_space(sip_header) != 0) {
rack_value->sip_value_state = SIP_VALUE_BAD;
rack_value->sip_value_end = sip_header->sip_hdr_end - 2;
goto rack_parse_done;
}
if (sip_atoi(sip_header, &rack_value->rack_cseq)) {
rack_value->sip_value_state = SIP_VALUE_BAD;
rack_value->sip_value_end = sip_header->sip_hdr_end - 2;
goto rack_parse_done;
}
if (sip_skip_white_space(sip_header) != 0) {
rack_value->sip_value_state = SIP_VALUE_BAD;
rack_value->sip_value_end = sip_header->sip_hdr_end - 2;
goto rack_parse_done;
}
tmp_ptr = sip_header->sip_hdr_current;
if (sip_find_white_space(sip_header)) {
rack_value->sip_value_state = SIP_VALUE_BAD;
rack_value->sip_value_end = sip_header->sip_hdr_end - 2;
goto rack_parse_done;
}
len = sip_header->sip_hdr_current - tmp_ptr;
for (i = 1; i < MAX_SIP_METHODS; i++) {
if (strncmp(sip_methods[i].name, tmp_ptr, len) == 0)
break;
}
if (i >= MAX_SIP_METHODS) {
rack_value->sip_value_state = SIP_VALUE_BAD;
rack_value->sip_value_end = sip_header->sip_hdr_end - 2;
goto rack_parse_done;
}
rack_value->rack_method = i;
rack_value->sip_value_end = sip_header->sip_hdr_current;
rack_parse_done:
sip_header->sip_hdr_parsed = parsed_header;
*header = parsed_header;
return (0);
}
int
sip_parse_allow_events_header(_sip_header_t *sip_header,
sip_parsed_header_t **header)
{
return (sip_parse_hdr_parser1(sip_header, header, 0));
}
int
sip_parse_event_header(_sip_header_t *sip_header, sip_parsed_header_t **header)
{
return (sip_parse_hdr_parser1(sip_header, header, 0));
}
int
sip_parse_substate_header(_sip_header_t *sip_header,
sip_parsed_header_t **header)
{
return (sip_parse_hdr_parser1(sip_header, header, 0));
}
int
sip_parse_author_header(_sip_header_t *sip_header,
sip_parsed_header_t **header)
{
return (sip_parse_hdr_parser5(sip_header, header, B_TRUE));
}
int
sip_parse_ainfo_header(_sip_header_t *sip_header,
sip_parsed_header_t **header)
{
return (sip_parse_hdr_parser1(sip_header, header, 0));
}
int
sip_parse_pauthen_header(_sip_header_t *sip_header,
sip_parsed_header_t **header)
{
return (sip_parse_hdr_parser5(sip_header, header, B_TRUE));
}
int
sip_parse_pauthor_header(_sip_header_t *sip_header,
sip_parsed_header_t **header)
{
return (sip_parse_hdr_parser5(sip_header, header, B_TRUE));
}
int
sip_parse_preq_header(_sip_header_t *sip_header,
sip_parsed_header_t **header)
{
return (sip_parse_hdr_parser1(sip_header, header, 0));
}
int
sip_parse_wauthen_header(_sip_header_t *sip_header,
sip_parsed_header_t **header)
{
return (sip_parse_hdr_parser5(sip_header, header, B_TRUE));
}
int
sip_parse_cid_header(_sip_header_t *sip_header, sip_parsed_header_t **header)
{
return (sip_parse_hdr_parser4(sip_header, header));
}
int
sip_parse_cseq_header(_sip_header_t *sip_header, sip_parsed_header_t **header)
{
sip_parsed_header_t *parsed_header;
sip_hdr_value_t *cseq_value;
int len;
char *tmp_ptr;
int i;
int ret;
if ((ret = sip_prim_parsers(sip_header, header)) != 0)
return (ret);
if (*header != NULL)
return (0);
parsed_header = calloc(1, sizeof (sip_parsed_header_t));
if (parsed_header == NULL)
return (ENOMEM);
parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1;
parsed_header->sip_header = sip_header;
parsed_header->value = calloc(1, sizeof (sip_hdr_value_t));
if (parsed_header->value == NULL) {
free(parsed_header);
return (ENOMEM);
}
cseq_value = (sip_hdr_value_t *)parsed_header->value;
cseq_value->sip_value_version = SIP_VALUE_VERSION_1;
cseq_value->sip_value_start = sip_header->sip_hdr_current;
if (sip_atoi(sip_header, &cseq_value->cseq_num)) {
cseq_value->sip_value_state = SIP_VALUE_BAD;
cseq_value->sip_value_end = sip_header->sip_hdr_end - 2;
goto cseq_parse_done;
}
cseq_value->sip_value_header = parsed_header;
if (sip_skip_white_space(sip_header) != 0) {
cseq_value->sip_value_state = SIP_VALUE_BAD;
cseq_value->sip_value_end = sip_header->sip_hdr_end - 2;
goto cseq_parse_done;
}
tmp_ptr = sip_header->sip_hdr_current;
if (sip_find_white_space(sip_header)) {
cseq_value->sip_value_state = SIP_VALUE_BAD;
cseq_value->sip_value_end = sip_header->sip_hdr_current;
goto cseq_parse_done;
}
len = sip_header->sip_hdr_current - tmp_ptr;
for (i = 1; i < MAX_SIP_METHODS; i++) {
if (strncmp(sip_methods[i].name, tmp_ptr, len) == 0)
break;
}
if (i >= MAX_SIP_METHODS) {
cseq_value->sip_value_state = SIP_VALUE_BAD;
cseq_value->sip_value_end = sip_header->sip_hdr_current;
goto cseq_parse_done;
}
cseq_value->cseq_method = i;
cseq_value->sip_value_end = sip_header->sip_hdr_current;
cseq_parse_done:
sip_header->sip_hdr_parsed = parsed_header;
*header = parsed_header;
return (0);
}
int
sip_parse_via_header(_sip_header_t *sip_header, sip_parsed_header_t **header)
{
sip_parsed_header_t *parsed_header;
int ret;
sip_hdr_value_t *value = NULL;
sip_hdr_value_t *last_value = NULL;
if ((ret = sip_prim_parsers(sip_header, header)) != 0)
return (ret);
if (*header != NULL)
return (0);
parsed_header = calloc(1, sizeof (sip_parsed_header_t));
if (parsed_header == NULL)
return (ENOMEM);
parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1;
parsed_header->sip_header = sip_header;
while (sip_header->sip_hdr_current < sip_header->sip_hdr_end) {
value = calloc(1, sizeof (sip_hdr_value_t));
if (value == NULL) {
sip_free_phdr(parsed_header);
return (ENOMEM);
}
if (last_value != NULL)
last_value->sip_next_value = value;
else
parsed_header->value = (sip_value_t *)value;
value->sip_value_version = SIP_VALUE_VERSION_1;
value->sip_value_start = sip_header->sip_hdr_current;
value->sip_value_header = parsed_header;
value->via_protocol_name.sip_str_ptr =
sip_header->sip_hdr_current;
if (sip_get_protocol_version(sip_header,
&value->via_protocol) != 0) {
if (sip_goto_next_value(sip_header) != 0) {
sip_free_phdr(parsed_header);
return (EPROTO);
}
value->sip_value_state = SIP_VALUE_BAD;
goto get_next_via_value;
}
if (sip_find_token(sip_header, SIP_SLASH) != 0) {
if (sip_goto_next_value(sip_header) != 0) {
sip_free_phdr(parsed_header);
return (EPROTO);
}
value->sip_value_state = SIP_VALUE_BAD;
goto get_next_via_value;
}
if (sip_skip_white_space(sip_header) != 0) {
if (sip_goto_next_value(sip_header) != 0) {
sip_free_phdr(parsed_header);
return (EPROTO);
}
value->sip_value_state = SIP_VALUE_BAD;
goto get_next_via_value;
}
value->via_protocol_transport.sip_str_ptr =
sip_header->sip_hdr_current;
if (sip_find_white_space(sip_header) != 0) {
if (sip_goto_next_value(sip_header) != 0) {
sip_free_phdr(parsed_header);
return (EPROTO);
}
value->sip_value_state = SIP_VALUE_BAD;
goto get_next_via_value;
}
value->via_protocol_transport.sip_str_len =
sip_header->sip_hdr_current -
value->via_protocol_transport.sip_str_ptr;
if (sip_skip_white_space(sip_header) != 0) {
if (sip_goto_next_value(sip_header) != 0) {
sip_free_phdr(parsed_header);
return (EPROTO);
}
value->sip_value_state = SIP_VALUE_BAD;
goto get_next_via_value;
}
value->via_sent_by_host.sip_str_ptr =
sip_header->sip_hdr_current;
if (*sip_header->sip_hdr_current == '[') {
if (sip_find_token(sip_header, ']')) {
if (sip_goto_next_value(sip_header) != 0) {
sip_free_phdr(parsed_header);
return (EPROTO);
}
value->sip_value_state = SIP_VALUE_BAD;
goto get_next_via_value;
}
} else if (sip_find_separator(sip_header, SIP_SEMI, SIP_COMMA,
SIP_HCOLON, B_FALSE)) {
if (sip_goto_next_value(sip_header) != 0) {
sip_free_phdr(parsed_header);
return (EPROTO);
}
value->sip_value_state = SIP_VALUE_BAD;
goto get_next_via_value;
}
value->via_sent_by_host.sip_str_len =
sip_header->sip_hdr_current -
value->via_sent_by_host.sip_str_ptr;
if (sip_skip_white_space(sip_header) != 0) {
if (sip_goto_next_value(sip_header) != 0) {
sip_free_phdr(parsed_header);
return (EPROTO);
}
value->sip_value_state = SIP_VALUE_BAD;
goto get_next_via_value;
}
if (*sip_header->sip_hdr_current == SIP_HCOLON) {
sip_header->sip_hdr_current++;
if (sip_atoi(sip_header, &value->via_sent_by_port) !=
0) {
if (sip_goto_next_value(sip_header) != 0) {
sip_free_phdr(parsed_header);
return (EPROTO);
}
value->sip_value_state = SIP_VALUE_BAD;
goto get_next_via_value;
}
}
if (value->via_sent_by_host.sip_str_len == 0 ||
(!isalnum(*value->via_sent_by_host.sip_str_ptr) &&
*value->via_sent_by_host.sip_str_ptr != '[')) {
if (sip_goto_next_value(sip_header) != 0) {
sip_free_phdr(parsed_header);
return (EPROTO);
}
value->sip_value_state = SIP_VALUE_BAD;
goto get_next_via_value;
}
ret = sip_parse_params(sip_header, &value->sip_param_list);
if (ret == EPROTO) {
value->sip_value_state = SIP_VALUE_BAD;
} else if (ret != 0) {
sip_free_phdr(parsed_header);
return (ret);
}
get_next_via_value:
value->sip_value_end = sip_header->sip_hdr_current;
if (sip_find_token(sip_header, SIP_COMMA) != 0)
break;
last_value = value;
(void) sip_skip_white_space(sip_header);
}
sip_header->sip_hdr_parsed = parsed_header;
*header = parsed_header;
return (0);
}
int
sip_parse_maxf_header(_sip_header_t *sip_header, sip_parsed_header_t **header)
{
return (sip_parse_hdr_parser2(sip_header, header, SIP_INT_VAL));
}
int
sip_parse_ctype_header(_sip_header_t *sip_header, sip_parsed_header_t **header)
{
return (sip_parse_hdr_parser1(sip_header, header, SIP_SLASH));
}
int
sip_parse_clen_header(_sip_header_t *sip_header, sip_parsed_header_t **header)
{
return (sip_parse_hdr_parser2(sip_header, header, SIP_INT_VAL));
}
int
sip_parse_cftr_header(_sip_header_t *sip_header, sip_parsed_header_t **header)
{
sip_parsed_header_t *parsed_header;
char *tmp_ptr;
char *tmp_ptr_2;
int ret;
sip_hdr_value_t *value = NULL;
sip_hdr_value_t *last_value = NULL;
if ((ret = sip_prim_parsers(sip_header, header)) != 0)
return (ret);
if (*header != NULL)
return (0);
parsed_header = calloc(1, sizeof (sip_parsed_header_t));
if (parsed_header == NULL)
return (ENOMEM);
parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1;
parsed_header->sip_header = sip_header;
while (sip_header->sip_hdr_current < sip_header->sip_hdr_end) {
boolean_t quoted_name = B_FALSE;
value = calloc(1, sizeof (sip_hdr_value_t));
if (value == NULL) {
sip_free_cftr_header(parsed_header);
return (ENOMEM);
}
if (last_value != NULL)
last_value->sip_next_value = value;
else
parsed_header->value = (sip_value_t *)value;
if (*sip_header->sip_hdr_current == SIP_QUOTE) {
sip_header->sip_hdr_current++;
quoted_name = B_TRUE;
}
value->sip_value_version = SIP_VALUE_VERSION_1;
value->sip_value_start = sip_header->sip_hdr_current;
value->sip_value_header = parsed_header;
if (*sip_header->sip_hdr_current != SIP_LAQUOT) {
tmp_ptr = sip_header->sip_hdr_current;
if (quoted_name &&
sip_find_token(sip_header, SIP_QUOTE) != 0) {
if (sip_goto_next_value(sip_header) != 0) {
sip_free_cftr_header(parsed_header);
return (EPROTO);
}
value->sip_value_state = SIP_VALUE_BAD;
goto get_next_cftr_value;
} else if (sip_find_separator(sip_header, SIP_SEMI,
SIP_LAQUOT, SIP_COMMA, B_TRUE) != 0) {
value->cftr_uri.sip_str_ptr = tmp_ptr;
value->cftr_uri.sip_str_len =
sip_header->sip_hdr_current - tmp_ptr;
if (value->cftr_uri.sip_str_len == 0) {
if (sip_goto_next_value(sip_header) !=
0) {
sip_free_cftr_header(
parsed_header);
return (EPROTO);
}
value->sip_value_state = SIP_VALUE_BAD;
goto get_next_cftr_value;
}
goto get_next_cftr_value;
}
--sip_header->sip_hdr_current;
(void) sip_reverse_skip_white_space(sip_header);
++sip_header->sip_hdr_current;
tmp_ptr_2 = sip_header->sip_hdr_current;
if (*sip_header->sip_hdr_current == SIP_SP) {
if (sip_skip_white_space(sip_header) != 0) {
value->cftr_uri.sip_str_ptr = tmp_ptr;
value->cftr_uri.sip_str_len =
tmp_ptr_2 - tmp_ptr;
if (value->cftr_uri.sip_str_len == 0) {
if (sip_goto_next_value(
sip_header) != 0) {
sip_free_cftr_header(
parsed_header);
return (EPROTO);
}
value->sip_value_state =
SIP_VALUE_BAD;
goto get_next_cftr_value;
}
goto get_next_cftr_value;
}
}
if (*sip_header->sip_hdr_current != SIP_LAQUOT) {
value->cftr_uri.sip_str_ptr = tmp_ptr;
value->cftr_uri.sip_str_len = tmp_ptr_2 -
tmp_ptr;
if (value->cftr_uri.sip_str_len == 0) {
if (sip_goto_next_value(sip_header) !=
0) {
sip_free_cftr_header(
parsed_header);
return (EPROTO);
}
value->sip_value_state = SIP_VALUE_BAD;
goto get_next_cftr_value;
}
goto get_params;
}
value->cftr_name = malloc(sizeof (sip_str_t));
if (value->cftr_name == NULL) {
sip_free_cftr_header(parsed_header);
return (ENOMEM);
}
value->cftr_name->sip_str_ptr = tmp_ptr;
value->cftr_name->sip_str_len = tmp_ptr_2 - tmp_ptr;
if (quoted_name)
value->cftr_name->sip_str_len--;
}
if (sip_find_token(sip_header, SIP_LAQUOT) != 0) {
if (sip_goto_next_value(sip_header) != 0) {
sip_free_cftr_header(parsed_header);
return (EPROTO);
}
value->sip_value_state = SIP_VALUE_BAD;
goto get_next_cftr_value;
}
if (*sip_header->sip_hdr_current == SIP_SP) {
if (sip_skip_white_space(sip_header) != 0) {
if (sip_goto_next_value(sip_header) != 0) {
sip_free_cftr_header(parsed_header);
return (EPROTO);
}
value->sip_value_state = SIP_VALUE_BAD;
goto get_next_cftr_value;
}
}
tmp_ptr = sip_header->sip_hdr_current;
if (sip_find_separator(sip_header, SIP_RAQUOT, 0, 0, B_FALSE)) {
if (sip_goto_next_value(sip_header) != 0) {
sip_free_cftr_header(parsed_header);
return (EPROTO);
}
value->sip_value_state = SIP_VALUE_BAD;
goto get_next_cftr_value;
}
value->cftr_uri.sip_str_ptr = tmp_ptr;
value->cftr_uri.sip_str_len =
sip_header->sip_hdr_current - tmp_ptr;
if (sip_find_token(sip_header, SIP_RAQUOT) != 0) {
if (sip_goto_next_value(sip_header) != 0) {
sip_free_cftr_header(parsed_header);
return (EINVAL);
}
value->sip_value_state = SIP_VALUE_BAD;
goto get_next_cftr_value;
}
if (value->cftr_uri.sip_str_len <= strlen("<>")) {
if (sip_goto_next_value(sip_header) != 0) {
sip_free_cftr_header(parsed_header);
return (EPROTO);
}
value->sip_value_state = SIP_VALUE_BAD;
goto get_next_cftr_value;
}
get_params:
ret = sip_parse_params(sip_header, &value->sip_param_list);
if (ret == EPROTO) {
value->sip_value_state = SIP_VALUE_BAD;
} else if (ret != 0) {
sip_free_cftr_header(parsed_header);
return (ret);
}
get_next_cftr_value:
value->sip_value_end = sip_header->sip_hdr_current;
if (value->cftr_uri.sip_str_len > 0) {
int error;
uint_t uri_errflags;
char *uri = "*";
_sip_msg_t *sip_msg;
sip_message_type_t *msg_type;
value->sip_value_parsed_uri = sip_parse_uri(
&value->cftr_uri, &error);
if (value->sip_value_parsed_uri == NULL) {
sip_free_cftr_header(parsed_header);
return (ENOMEM);
}
uri_errflags = ((_sip_uri_t *)value->
sip_value_parsed_uri)->sip_uri_errflags;
if (error != 0 || uri_errflags != 0) {
if ((strcmp(SIP_CONTACT, sip_header->
sip_header_functions->header_name) == 0) &&
(strncmp(value->cftr_uri.sip_str_ptr, uri,
strlen(uri)) == 0) && (strlen(uri) ==
value->cftr_uri.sip_str_len)) {
sip_msg = sip_header->sip_hdr_sipmsg;
msg_type = sip_msg->sip_msg_req_res;
if (msg_type->is_request && msg_type->
sip_req_method == REGISTER) {
error = 0;
((_sip_uri_t *)value->
sip_value_parsed_uri)->
sip_uri_errflags = 0;
} else {
value->sip_value_state =
SIP_VALUE_BAD;
}
} else {
value->sip_value_state = SIP_VALUE_BAD;
}
}
}
(void) sip_find_token(sip_header, SIP_COMMA);
last_value = value;
(void) sip_skip_white_space(sip_header);
}
sip_header->sip_hdr_parsed = parsed_header;
*header = parsed_header;
return (0);
}
int
sip_parse_passertedid(_sip_header_t *sip_header, sip_parsed_header_t **header)
{
return (sip_parse_hdr_parser3(sip_header, header, SIP_STRS_VAL,
B_TRUE));
}
int
sip_parse_ppreferredid(_sip_header_t *sip_header, sip_parsed_header_t **header)
{
return (sip_parse_hdr_parser3(sip_header, header, SIP_STRS_VAL,
B_TRUE));
}
int
sip_parse_unknown_header(_sip_header_t *sip_header,
sip_parsed_header_t **header)
{
return (EINVAL);
}