12882Svi117747 /* 22882Svi117747 * CDDL HEADER START 32882Svi117747 * 42882Svi117747 * The contents of this file are subject to the terms of the 52882Svi117747 * Common Development and Distribution License (the "License"). 62882Svi117747 * You may not use this file except in compliance with the License. 72882Svi117747 * 82882Svi117747 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 92882Svi117747 * or http://www.opensolaris.org/os/licensing. 102882Svi117747 * See the License for the specific language governing permissions 112882Svi117747 * and limitations under the License. 122882Svi117747 * 132882Svi117747 * When distributing Covered Code, include this CDDL HEADER in each 142882Svi117747 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 152882Svi117747 * If applicable, add the following below this CDDL HEADER, with the 162882Svi117747 * fields enclosed by brackets "[]" replaced with your own identifying 172882Svi117747 * information: Portions Copyright [yyyy] [name of copyright owner] 182882Svi117747 * 192882Svi117747 * CDDL HEADER END 202882Svi117747 */ 212882Svi117747 222882Svi117747 /* 23*3439Svi117747 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 242882Svi117747 * Use is subject to license terms. 252882Svi117747 */ 262882Svi117747 272882Svi117747 #pragma ident "%Z%%M% %I% %E% SMI" 282882Svi117747 29*3439Svi117747 #include <ctype.h> 30*3439Svi117747 #include <errno.h> 31*3439Svi117747 #include <stdlib.h> 32*3439Svi117747 #include <strings.h> 33*3439Svi117747 #include <sip.h> 34*3439Svi117747 352882Svi117747 #include "sip_msg.h" 362882Svi117747 #include "sip_miscdefs.h" 372882Svi117747 #include "sip_parse_generic.h" 38*3439Svi117747 #include "sip_parse_uri.h" 39*3439Svi117747 402882Svi117747 412882Svi117747 /* 422882Svi117747 * Accept = "Accept" HCOLON [ accept-range *(COMMA accept-range) ] 432882Svi117747 * accept-range = media-range *(SEMI accept-param) 442882Svi117747 * media-range = ("* / *" | (m-type SLASH "*") | (m-type SLASH m-subtype)) 452882Svi117747 * *(SEMI m-param) 462882Svi117747 * accept-param = ("q" EQUAL qvalue) | generic-param 472882Svi117747 * qvalue = ("0" ["." 0*3DIGIT]) | ("1" ["." 0*3DIGIT]) 482882Svi117747 * generic-param = token [ EQUAL gen-value] 492882Svi117747 * gen-value = token | host | quoted-str 502882Svi117747 */ 512882Svi117747 int 522882Svi117747 sip_parse_acpt_header(_sip_header_t *sip_header, sip_parsed_header_t **header) 532882Svi117747 { 542882Svi117747 if (sip_is_empty_hdr(sip_header)) 552882Svi117747 return (sip_parse_hdr_empty(sip_header, header)); 562882Svi117747 return (sip_parse_hdr_parser1(sip_header, header, SIP_SLASH)); 572882Svi117747 } 582882Svi117747 592882Svi117747 /* 602882Svi117747 * Accept-Encoding = "Accept-Encoding" ":" 1#(codings [ ";" "q" "=" qval]) 612882Svi117747 * codings = (content-coding | "*") 622882Svi117747 * content-coding = token 632882Svi117747 */ 642882Svi117747 int 652882Svi117747 sip_parse_acpt_encode_header(_sip_header_t *sip_header, 662882Svi117747 sip_parsed_header_t **header) 672882Svi117747 { 682882Svi117747 return (sip_parse_hdr_parser1(sip_header, header, (char)NULL)); 692882Svi117747 } 702882Svi117747 712882Svi117747 /* 722882Svi117747 * Accept-Language = "Accept-Language" ":" [ lang * (COMMA lang) ] 732882Svi117747 * lang = lang-range *(SEMI accept-param) 742882Svi117747 * lang-range = ((1*8ALPHA * ("-" 1*8ALPHA)) | "*" 752882Svi117747 */ 762882Svi117747 int 772882Svi117747 sip_parse_acpt_lang_header(_sip_header_t *sip_header, 782882Svi117747 sip_parsed_header_t **header) 792882Svi117747 { 802882Svi117747 if (sip_is_empty_hdr(sip_header)) 812882Svi117747 return (sip_parse_hdr_empty(sip_header, header)); 822882Svi117747 return (sip_parse_hdr_parser1(sip_header, header, (char)NULL)); 832882Svi117747 } 842882Svi117747 852882Svi117747 /* 862882Svi117747 * Alert-Info = "Alert-Info" ":" alert-param *(COMMA alert-param) 872882Svi117747 * alert-param = LAQUOT absoluteURI RAQUOT * (SEMI generic-param) 882882Svi117747 */ 892882Svi117747 int 902882Svi117747 sip_parse_alert_header(_sip_header_t *sip_header, sip_parsed_header_t **header) 912882Svi117747 { 922882Svi117747 return (sip_parse_hdr_parser3(sip_header, header, SIP_STR_VAL, B_TRUE)); 932882Svi117747 } 942882Svi117747 952882Svi117747 /* 962882Svi117747 * Allow = "Allow" ":" method-name1[, method-name2..] 972882Svi117747 */ 982882Svi117747 int 992882Svi117747 sip_parse_allow_header(_sip_header_t *hdr, sip_parsed_header_t **phdr) 1002882Svi117747 { 1012882Svi117747 sip_parsed_header_t *parsed_header; 1022882Svi117747 sip_hdr_value_t *value = NULL; 1032882Svi117747 sip_hdr_value_t *last_value = NULL; 1042882Svi117747 int len; 1052882Svi117747 int i; 1062882Svi117747 int ret; 1072882Svi117747 boolean_t multi_value = B_FALSE; 1082882Svi117747 1092882Svi117747 if ((ret = sip_prim_parsers(hdr, phdr)) != 0) 1102882Svi117747 return (ret); 1112882Svi117747 1122882Svi117747 if (*phdr != NULL) 1132882Svi117747 return (0); 1142882Svi117747 1152882Svi117747 parsed_header = calloc(1, sizeof (sip_parsed_header_t)); 1162882Svi117747 if (parsed_header == NULL) 1172882Svi117747 return (ENOMEM); 1182882Svi117747 parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1; 1192882Svi117747 parsed_header->sip_header = hdr; 1202882Svi117747 1212882Svi117747 while (hdr->sip_hdr_current < hdr->sip_hdr_end) { 1222882Svi117747 value = calloc(1, sizeof (sip_hdr_value_t)); 1232882Svi117747 if (value == NULL) { 1242882Svi117747 sip_free_phdr(parsed_header); 1252882Svi117747 return (ENOMEM); 1262882Svi117747 } 1272882Svi117747 if (last_value != NULL) 1282882Svi117747 last_value->sip_next_value = value; 1292882Svi117747 else 1302882Svi117747 parsed_header->value = (sip_value_t *)value; 1312882Svi117747 1322882Svi117747 value->sip_value_start = hdr->sip_hdr_current; 1332882Svi117747 value->sip_value_header = parsed_header; 1342882Svi117747 1352882Svi117747 if (sip_find_separator(hdr, SIP_COMMA, (char)NULL, 1362882Svi117747 (char)NULL) == 0) { 1372882Svi117747 multi_value = B_TRUE; 1382882Svi117747 } 1392882Svi117747 1402882Svi117747 len = hdr->sip_hdr_current - value->sip_value_start; 1412882Svi117747 for (i = 1; i < MAX_SIP_METHODS; i++) { 1422882Svi117747 if (strncmp(sip_methods[i].name, value->sip_value_start, 1432882Svi117747 len) == 0) { 1442882Svi117747 break; 1452882Svi117747 } 1462882Svi117747 } 1472882Svi117747 if (i >= MAX_SIP_METHODS) { 1482882Svi117747 value->int_val = 0; 1492882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 1502882Svi117747 if (multi_value) 1512882Svi117747 goto next_val; 1522882Svi117747 else 1532882Svi117747 goto end; 1542882Svi117747 } 1552882Svi117747 value->int_val = i; 1562882Svi117747 if (!multi_value) 1572882Svi117747 goto end; 1582882Svi117747 next_val: 1592882Svi117747 if (sip_find_token(hdr, SIP_COMMA) != 0) 1602882Svi117747 break; 1612882Svi117747 value->sip_value_end = hdr->sip_hdr_current - 1; 1622882Svi117747 last_value = value; 1632882Svi117747 (void) sip_skip_white_space(hdr); 1642882Svi117747 } 1652882Svi117747 1662882Svi117747 end: 1672882Svi117747 *phdr = parsed_header; 1682882Svi117747 return (0); 1692882Svi117747 } 1702882Svi117747 1712882Svi117747 1722882Svi117747 /* 1732882Svi117747 * Call-Info = "Call-Info" HCOLON info * (COMMA info) 1742882Svi117747 * info = LAQUOT absoluteURI RAQUOT * (SEMI info-param) 1752882Svi117747 * info-param = ("purpose" EQUAL ("icon" | "info" | "card" | token)) | 1762882Svi117747 * generic-param 1772882Svi117747 */ 1782882Svi117747 int 1792882Svi117747 sip_parse_callinfo_header(_sip_header_t *sip_header, 1802882Svi117747 sip_parsed_header_t **header) 1812882Svi117747 { 1822882Svi117747 return (sip_parse_hdr_parser3(sip_header, header, SIP_STR_VAL, B_TRUE)); 1832882Svi117747 } 1842882Svi117747 1852882Svi117747 /* 1862882Svi117747 * Content-Disposition = "Content-Disposition" HCOLON disp-type * 1872882Svi117747 * (SEMI disp-param) 1882882Svi117747 * disp-type = "render" | "session" | "icon" | "alert" | disp-ext-token 1892882Svi117747 * disp-param = handling-param | generic-param 1902882Svi117747 * handling-param = "handling" EQUAL("optional" | "required" | other-handling) 1912882Svi117747 * other-handling = token 1922882Svi117747 * disp-ext-token = token 1932882Svi117747 * 1942882Svi117747 */ 1952882Svi117747 int 1962882Svi117747 sip_parse_contentdis_header(_sip_header_t *sip_header, 1972882Svi117747 sip_parsed_header_t **header) 1982882Svi117747 { 1992882Svi117747 return (sip_parse_hdr_parser1(sip_header, header, (char)NULL)); 2002882Svi117747 } 2012882Svi117747 2022882Svi117747 /* 2032882Svi117747 * Content-Encoding = ("Content-Encoding" | "e") HCOLON content-coding * 2042882Svi117747 * (COMMA content-coding) 2052882Svi117747 */ 2062882Svi117747 int 2072882Svi117747 sip_parse_contentencode_header(_sip_header_t *sip_header, 2082882Svi117747 sip_parsed_header_t **header) 2092882Svi117747 { 2102882Svi117747 return (sip_parse_hdr_parser1(sip_header, header, (char)NULL)); 2112882Svi117747 } 2122882Svi117747 2132882Svi117747 /* 2142882Svi117747 * Content-Language = ("Content-Language" | "l") HCOLON lang-tag * 2152882Svi117747 * (COMMA lang-tag) 2162882Svi117747 * lang-tag = primary-tag *("-" subtag) 2172882Svi117747 * prmary-tag = 1*8ALPHA 2182882Svi117747 * subtag = 1*8ALPHA 2192882Svi117747 */ 2202882Svi117747 int 2212882Svi117747 sip_parse_contentlang_header(_sip_header_t *sip_header, 2222882Svi117747 sip_parsed_header_t **header) 2232882Svi117747 { 2242882Svi117747 return (sip_parse_hdr_parser1(sip_header, header, (char)NULL)); 2252882Svi117747 } 2262882Svi117747 2272882Svi117747 /* 2282882Svi117747 * Date = "Date" HCOLON SIPdate 2292882Svi117747 * SIPdate = wkday "," SP date1 SP time SP "GMT" 2302882Svi117747 * date1 = 2DIGIT SP mnth SP 4DIGIT; day month year 2312882Svi117747 * time = 2DIGIT ":" 2DIGIT ":" 2DIGIT 2322882Svi117747 * wkday = "Mon" | "Tue" | "Wed" | "Thu" | "Fri" | "Sat" | "Sun" 2332882Svi117747 * month = "Jan" | "Feb" etc 2342882Svi117747 */ 2352882Svi117747 int 2362882Svi117747 sip_parse_date_header(_sip_header_t *sip_header, sip_parsed_header_t **header) 2372882Svi117747 { 2382882Svi117747 sip_parsed_header_t *parsed_header; 2392882Svi117747 int r; 2402882Svi117747 sip_hdr_value_t *value = NULL; 2412882Svi117747 2422882Svi117747 if ((r = sip_prim_parsers(sip_header, header)) != 0) 2432882Svi117747 return (r); 2442882Svi117747 2452882Svi117747 if (*header != NULL) 2462882Svi117747 return (0); 2472882Svi117747 2482882Svi117747 parsed_header = calloc(1, sizeof (sip_parsed_header_t)); 2492882Svi117747 if (parsed_header == NULL) 2502882Svi117747 return (ENOMEM); 2512882Svi117747 parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1; 2522882Svi117747 parsed_header->sip_header = sip_header; 2532882Svi117747 2542882Svi117747 value = calloc(1, sizeof (sip_hdr_value_t)); 2552882Svi117747 if (value == NULL) { 2562882Svi117747 sip_free_phdr(parsed_header); 2572882Svi117747 return (ENOMEM); 2582882Svi117747 } 2592882Svi117747 parsed_header->value = (sip_value_t *)value; 2602882Svi117747 2612882Svi117747 value->sip_value_start = sip_header->sip_hdr_current; 2622882Svi117747 value->sip_value_header = parsed_header; 2632882Svi117747 value->date_wd_ptr = sip_header->sip_hdr_current; 2642882Svi117747 if (sip_find_token(sip_header, SIP_COMMA) == 0) { 2652882Svi117747 value->date_wd_len = sip_header->sip_hdr_current - 2662882Svi117747 value->date_wd_ptr - 1; 2672882Svi117747 sip_header->sip_hdr_current++; 2682882Svi117747 if (sip_skip_white_space(sip_header) != 0) { 2692882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 2702882Svi117747 return (EPROTO); 2712882Svi117747 } 2722882Svi117747 } else { 2732882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 2742882Svi117747 return (EPROTO); 2752882Svi117747 } 2762882Svi117747 2772882Svi117747 if (sip_skip_white_space(sip_header) != 0) { 2782882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 2792882Svi117747 return (EPROTO); 2802882Svi117747 } 2812882Svi117747 r = sip_atoi(sip_header, &value->date_d); 2822882Svi117747 if (r != 0 || value->date_d < 0 || value->date_d > 31) { 2832882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 2842882Svi117747 return (EPROTO); 2852882Svi117747 } 2862882Svi117747 if (sip_skip_white_space(sip_header) != 0) { 2872882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 2882882Svi117747 return (EPROTO); 2892882Svi117747 } 2902882Svi117747 value->date_m_ptr = sip_header->sip_hdr_current; 2912882Svi117747 if (sip_find_token(sip_header, SIP_SP) == 0) { 2922882Svi117747 value->date_m_len = sip_header->sip_hdr_current - 2932882Svi117747 value->date_m_ptr - 1; 2942882Svi117747 } else { 2952882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 2962882Svi117747 return (EPROTO); 2972882Svi117747 } 2982882Svi117747 2992882Svi117747 r = sip_atoi(sip_header, &value->date_y); 3002882Svi117747 if (r != 0 || value->date_y < 0) { 3012882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 3022882Svi117747 return (EPROTO); 3032882Svi117747 } 3042882Svi117747 if (sip_skip_white_space(sip_header) != 0) { 3052882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 3062882Svi117747 return (EPROTO); 3072882Svi117747 } 3082882Svi117747 value->date_t_ptr = sip_header->sip_hdr_current; 3092882Svi117747 if (sip_find_token(sip_header, SIP_SP) == 0) { 3102882Svi117747 value->date_t_len = sip_header->sip_hdr_current - 3112882Svi117747 value->date_t_ptr - 1; 3122882Svi117747 } else { 3132882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 3142882Svi117747 return (EPROTO); 3152882Svi117747 } 3162882Svi117747 3172882Svi117747 value->date_tz_ptr = sip_header->sip_hdr_current; 3182882Svi117747 /* 3192882Svi117747 * minus 2 to get rid of the CRLF 3202882Svi117747 */ 3212882Svi117747 value->date_tz_len = sip_header->sip_hdr_end - 3222882Svi117747 sip_header->sip_hdr_current - 2; 3232882Svi117747 3242882Svi117747 *header = parsed_header; 3252882Svi117747 3262882Svi117747 sip_header->sip_hdr_parsed = *header; 3272882Svi117747 return (0); 3282882Svi117747 } 3292882Svi117747 3302882Svi117747 /* 3312882Svi117747 * Error-Info = "Error-Info" HCOLON error-uri *(COMMA error-uri) 3322882Svi117747 * error-uri = LAQUOT absoluteURI RAQUOT *(SEMI generic-param) 3332882Svi117747 */ 3342882Svi117747 int 3352882Svi117747 sip_parse_errorinfo_header(_sip_header_t *sip_header, 3362882Svi117747 sip_parsed_header_t **header) 3372882Svi117747 { 3382882Svi117747 return (sip_parse_hdr_parser3(sip_header, header, SIP_STR_VAL, B_TRUE)); 3392882Svi117747 } 3402882Svi117747 3412882Svi117747 /* 3422882Svi117747 * Expires = "Expires" HCOLON delta-seconds 3432882Svi117747 */ 3442882Svi117747 int 3452882Svi117747 sip_parse_expire_header(_sip_header_t *sip_header, 3462882Svi117747 sip_parsed_header_t **header) 3472882Svi117747 { 3482882Svi117747 return (sip_parse_hdr_parser2(sip_header, header, SIP_INT_VAL)); 3492882Svi117747 } 3502882Svi117747 3512882Svi117747 /* 3522882Svi117747 * In-Reply-To = "In-Reply-To" HCOLON callid *(COMMA callid) 3532882Svi117747 */ 3542882Svi117747 int 3552882Svi117747 sip_parse_inreplyto_header(_sip_header_t *sip_header, 3562882Svi117747 sip_parsed_header_t **header) 3572882Svi117747 { 3582882Svi117747 return (sip_parse_hdr_parser1(sip_header, header, (char)NULL)); 3592882Svi117747 } 3602882Svi117747 3612882Svi117747 /* 3622882Svi117747 * RSeq = "RSeq" HCOLON response-num 3632882Svi117747 */ 3642882Svi117747 int 3652882Svi117747 sip_parse_rseq(_sip_header_t *sip_header, sip_parsed_header_t **header) 3662882Svi117747 { 3672882Svi117747 int r; 3682882Svi117747 sip_hdr_value_t *rseq_value; 3692882Svi117747 3702882Svi117747 r = sip_parse_hdr_parser2(sip_header, header, SIP_INT_VAL); 3712882Svi117747 /* 3722882Svi117747 * Additionally, a value of 0 is bad_value 3732882Svi117747 */ 3742882Svi117747 if (sip_header->sip_hdr_parsed != NULL && 3752882Svi117747 sip_header->sip_hdr_parsed->value != NULL) { 3762882Svi117747 rseq_value = (sip_hdr_value_t *) 3772882Svi117747 sip_header->sip_hdr_parsed->value; 3782882Svi117747 if (rseq_value->int_val == 0) 3792882Svi117747 rseq_value->sip_value_state = SIP_VALUE_BAD; 3802882Svi117747 } 3812882Svi117747 return (r); 3822882Svi117747 } 3832882Svi117747 3842882Svi117747 /* 3852882Svi117747 * Min-Expires = "Min-Expires" HCOLON delta-seconds 3862882Svi117747 */ 3872882Svi117747 int 3882882Svi117747 sip_parse_minexpire_header(_sip_header_t *sip_header, 3892882Svi117747 sip_parsed_header_t **header) 3902882Svi117747 { 3912882Svi117747 return (sip_parse_hdr_parser2(sip_header, header, SIP_INT_VAL)); 3922882Svi117747 } 3932882Svi117747 3942882Svi117747 /* 3952882Svi117747 * MIME-Version = "MIME-Version" HCOLON 1*DIGIT "." 1*DIGIT 3962882Svi117747 */ 3972882Svi117747 int 3982882Svi117747 sip_parse_mimeversion_header(_sip_header_t *sip_header, 3992882Svi117747 sip_parsed_header_t **header) 4002882Svi117747 { 4012882Svi117747 return (sip_parse_hdr_parser4(sip_header, header)); 4022882Svi117747 } 4032882Svi117747 4042882Svi117747 /* 4052882Svi117747 * Organization = "Organization" HCOLON [TEXT-UTF8-TRIM] 4062882Svi117747 */ 4072882Svi117747 int 4082882Svi117747 sip_parse_org_header(_sip_header_t *sip_header, 4092882Svi117747 sip_parsed_header_t **header) 4102882Svi117747 { 4112882Svi117747 if (sip_is_empty_hdr(sip_header)) 4122882Svi117747 return (sip_parse_hdr_empty(sip_header, header)); 4132882Svi117747 return (sip_parse_hdr_parser4(sip_header, header)); 4142882Svi117747 } 4152882Svi117747 4162882Svi117747 /* 4172882Svi117747 * Priority = "Priority" HCOLON priority-val 4182882Svi117747 * priority-val = "emergency" | "urgent" | "normal" | "non-urgent" | other 4192882Svi117747 * other = token 4202882Svi117747 */ 4212882Svi117747 int 4222882Svi117747 sip_parse_priority_header(_sip_header_t *sip_header, 4232882Svi117747 sip_parsed_header_t **header) 4242882Svi117747 { 4252882Svi117747 return (sip_parse_hdr_parser4(sip_header, header)); 4262882Svi117747 } 4272882Svi117747 4282882Svi117747 /* 4292882Svi117747 * Reply-To = "Reply-To" HCOLON rplyto-spec 4302882Svi117747 * rplyto-spec = (name-addr | addr-spec) *(SEMI rplyto-param) 4312882Svi117747 * rplyto-param = generic-param 4322882Svi117747 * name-addr = [ display-name ] LAQUOT addr-spec RAQUOT 4332882Svi117747 * addr-spec = SIP-URI | SIPS-URI | absolute URI 4342882Svi117747 */ 4352882Svi117747 int 4362882Svi117747 sip_parse_replyto_header(_sip_header_t *sip_header, 4372882Svi117747 sip_parsed_header_t **header) 4382882Svi117747 { 4392882Svi117747 return (sip_parse_hdr_parser3(sip_header, header, SIP_STRS_VAL, 4402882Svi117747 B_TRUE)); 4412882Svi117747 } 4422882Svi117747 4432882Svi117747 /* 4442882Svi117747 * PRIVACY = "Privacy" HCOLON priv-value *(COMMA priv-value) 4452882Svi117747 * priv-value = "header" / "session" / "user" / "none" / "critical" 4462882Svi117747 * / token / id 4472882Svi117747 */ 4482882Svi117747 int 4492882Svi117747 sip_parse_privacy_header(_sip_header_t *sip_header, 4502882Svi117747 sip_parsed_header_t **header) 4512882Svi117747 { 4522882Svi117747 return (sip_parse_hdr_parser1(sip_header, header, (char)NULL)); 4532882Svi117747 } 4542882Svi117747 4552882Svi117747 4562882Svi117747 /* 4572882Svi117747 * Require = "Require" HCOLON option-tag * (COMMA option-tag) 4582882Svi117747 */ 4592882Svi117747 int 4602882Svi117747 sip_parse_require_header(_sip_header_t *sip_header, 4612882Svi117747 sip_parsed_header_t **header) 4622882Svi117747 { 4632882Svi117747 return (sip_parse_hdr_parser1(sip_header, header, (char)NULL)); 4642882Svi117747 } 4652882Svi117747 4662882Svi117747 /* 4672882Svi117747 * Retry-After = "Retry-After" HCOLON delta-seconds [ comment ] * 4682882Svi117747 * (SEMI retry-param) 4692882Svi117747 * retry-param = "duration" EQUAL delta-seconds 4702882Svi117747 */ 4712882Svi117747 int 4722882Svi117747 sip_parse_retryaft_header(_sip_header_t *sip_header, 4732882Svi117747 sip_parsed_header_t **header) 4742882Svi117747 { 4752882Svi117747 sip_parsed_header_t *parsed_header; 4762882Svi117747 sip_hdr_value_t *value = NULL; 4772882Svi117747 int ret; 4782882Svi117747 4792882Svi117747 if ((ret = sip_prim_parsers(sip_header, header)) != 0) 4802882Svi117747 return (ret); 4812882Svi117747 4822882Svi117747 if (*header != NULL) 4832882Svi117747 return (0); 4842882Svi117747 4852882Svi117747 parsed_header = calloc(1, sizeof (sip_parsed_header_t)); 4862882Svi117747 if (parsed_header == NULL) 4872882Svi117747 return (ENOMEM); 4882882Svi117747 parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1; 4892882Svi117747 parsed_header->sip_header = sip_header; 4902882Svi117747 4912882Svi117747 value = calloc(1, sizeof (sip_hdr_value_t)); 4922882Svi117747 if (value == NULL) { 4932882Svi117747 sip_free_phdr(parsed_header); 4942882Svi117747 return (ENOMEM); 4952882Svi117747 } 4962882Svi117747 4972882Svi117747 parsed_header->value = (sip_value_t *)value; 4982882Svi117747 value->sip_value_start = sip_header->sip_hdr_current; 4992882Svi117747 value->sip_value_header = parsed_header; 5002882Svi117747 5012882Svi117747 ret = sip_atoi(sip_header, &(value->intstr_int)); 5022882Svi117747 if (ret != 0) 5032882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 5042882Svi117747 if (sip_find_token(sip_header, SIP_LPAR) == 0) { 5052882Svi117747 value->intstr_str_ptr = sip_header->sip_hdr_current; 5062882Svi117747 if (sip_find_token(sip_header, SIP_RPAR) == 0) { 5072882Svi117747 value->intstr_str_len = 5082882Svi117747 sip_header->sip_hdr_current - 5092882Svi117747 value->intstr_str_ptr - 1; 5102882Svi117747 if (sip_find_token(sip_header, SIP_SEMI) == 0) { 5112882Svi117747 sip_header->sip_hdr_current--; 5122882Svi117747 (void) sip_parse_params(sip_header, 5132882Svi117747 &(value->sip_param_list)); 5142882Svi117747 } 5152882Svi117747 } else { 5162882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 5172882Svi117747 return (EPROTO); 5182882Svi117747 } 5192882Svi117747 } else { 5202882Svi117747 value->intstr_str_ptr = NULL; 5212882Svi117747 value->intstr_str_len = 0; 5222882Svi117747 5232882Svi117747 /* 5242882Svi117747 * from value start, search if parameter list 5252882Svi117747 */ 5262882Svi117747 sip_header->sip_hdr_current = value->sip_value_start; 5272882Svi117747 if (sip_find_token(sip_header, SIP_SEMI) == 0) { 5282882Svi117747 sip_header->sip_hdr_current--; 5292882Svi117747 (void) sip_parse_params(sip_header, 5302882Svi117747 &(value->sip_param_list)); 5312882Svi117747 } 5322882Svi117747 } 5332882Svi117747 5342882Svi117747 *header = parsed_header; 5352882Svi117747 sip_header->sip_hdr_parsed = *header; 5362882Svi117747 return (0); 5372882Svi117747 } 5382882Svi117747 5392882Svi117747 /* 5402882Svi117747 * Server = "Server" HCOLON servel-val *(LWS server-val) 5412882Svi117747 * servel-val = product|comment 5422882Svi117747 * product = token [SLASH version] 5432882Svi117747 * version = token 5442882Svi117747 * Treated as one single string 5452882Svi117747 */ 5462882Svi117747 int 5472882Svi117747 sip_parse_server_header(_sip_header_t *sip_header, sip_parsed_header_t **header) 5482882Svi117747 { 5492882Svi117747 return (sip_parse_hdr_parser4(sip_header, header)); 5502882Svi117747 } 5512882Svi117747 5522882Svi117747 /* 5532882Svi117747 * Subject = ("Subject" | "s")HCOLON [TEXT-UTF8-TRIM] 5542882Svi117747 */ 5552882Svi117747 int 5562882Svi117747 sip_parse_subject_header(_sip_header_t *sip_header, 5572882Svi117747 sip_parsed_header_t **header) 5582882Svi117747 { 5592882Svi117747 if (sip_is_empty_hdr(sip_header)) 5602882Svi117747 return (sip_parse_hdr_empty(sip_header, header)); 5612882Svi117747 return (sip_parse_hdr_parser4(sip_header, header)); 5622882Svi117747 } 5632882Svi117747 5642882Svi117747 /* 5652882Svi117747 * Supported = ("Supported" | "k") HCOLON [option-tag * (COMMA option-tag) ] 5662882Svi117747 */ 5672882Svi117747 int 5682882Svi117747 sip_parse_support_header(_sip_header_t *sip_header, 5692882Svi117747 sip_parsed_header_t **header) 5702882Svi117747 { 5712882Svi117747 if (sip_is_empty_hdr(sip_header)) 5722882Svi117747 return (sip_parse_hdr_empty(sip_header, header)); 5732882Svi117747 return (sip_parse_hdr_parser1(sip_header, header, (char)NULL)); 5742882Svi117747 } 5752882Svi117747 5762882Svi117747 /* 5772882Svi117747 * Timestamp = "Timestamp" HCOLON 1*DIGIT ["." *(DIGIT)] [LWS delay] 5782882Svi117747 */ 5792882Svi117747 int 5802882Svi117747 sip_parse_timestamp_header(_sip_header_t *sip_header, 5812882Svi117747 sip_parsed_header_t **header) 5822882Svi117747 { 5832882Svi117747 sip_parsed_header_t *parsed_header; 5842882Svi117747 sip_hdr_value_t *value = NULL; 5852882Svi117747 int ret; 5862882Svi117747 5872882Svi117747 if ((ret = sip_prim_parsers(sip_header, header)) != 0) 5882882Svi117747 return (ret); 5892882Svi117747 5902882Svi117747 if (*header != NULL) 5912882Svi117747 return (0); 5922882Svi117747 5932882Svi117747 parsed_header = calloc(1, sizeof (sip_parsed_header_t)); 5942882Svi117747 if (parsed_header == NULL) 5952882Svi117747 return (ENOMEM); 5962882Svi117747 parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1; 5972882Svi117747 parsed_header->sip_header = sip_header; 5982882Svi117747 5992882Svi117747 value = calloc(1, sizeof (sip_hdr_value_t)); 6002882Svi117747 if (value == NULL) { 6012882Svi117747 sip_free_phdr(parsed_header); 6022882Svi117747 return (ENOMEM); 6032882Svi117747 } 6042882Svi117747 parsed_header->value = (sip_value_t *)value; 6052882Svi117747 6062882Svi117747 value->sip_value_start = sip_header->sip_hdr_current; 6072882Svi117747 value->sip_value_header = parsed_header; 6082882Svi117747 6092882Svi117747 if (sip_skip_white_space(sip_header) != 0) { 6102882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 6112882Svi117747 return (EPROTO); 6122882Svi117747 } 6132882Svi117747 value->strs1_val_ptr = sip_header->sip_hdr_current; 6142882Svi117747 6152882Svi117747 if (sip_find_white_space(sip_header) == 0) { 6162882Svi117747 /* 6172882Svi117747 * timestamp and delay, timestamp in str1, delay in str2 6182882Svi117747 */ 6192882Svi117747 value->strs1_val_len = sip_header->sip_hdr_current - 6202882Svi117747 value->strs1_val_ptr; 6212882Svi117747 (void) sip_skip_white_space(sip_header); 6222882Svi117747 6232882Svi117747 value->strs2_val_ptr = sip_header->sip_hdr_current; 6242882Svi117747 if (sip_find_cr(sip_header) != 0) { 6252882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 6262882Svi117747 return (EPROTO); 6272882Svi117747 } 6282882Svi117747 if (sip_header->sip_hdr_current < value->strs2_val_ptr) { 6292882Svi117747 value->strs2_val_ptr = NULL; 6302882Svi117747 value->strs2_val_len = 0; 6312882Svi117747 } else { 6322882Svi117747 value->strs2_val_len = sip_header->sip_hdr_current - 6332882Svi117747 value->strs2_val_ptr; 6342882Svi117747 } 6352882Svi117747 } else { 6362882Svi117747 /* 6372882Svi117747 * no delay information 6382882Svi117747 */ 6392882Svi117747 value->strs1_val_len = sip_header->sip_hdr_current 6402882Svi117747 - value->strs1_val_ptr; 6412882Svi117747 value->strs2_val_ptr = NULL; 6422882Svi117747 value->strs2_val_len = 0; 6432882Svi117747 } 6442882Svi117747 6452882Svi117747 *header = parsed_header; 6462882Svi117747 sip_header->sip_hdr_parsed = *header; 6472882Svi117747 6482882Svi117747 return (0); 6492882Svi117747 } 6502882Svi117747 /* 6512882Svi117747 * Unsupported = "Unsupported" HCOLON option-tag * (COMMA option-tag) 6522882Svi117747 */ 6532882Svi117747 int 6542882Svi117747 sip_parse_usupport_header(_sip_header_t *sip_header, 6552882Svi117747 sip_parsed_header_t **header) 6562882Svi117747 { 6572882Svi117747 return (sip_parse_hdr_parser1(sip_header, header, (char)NULL)); 6582882Svi117747 } 6592882Svi117747 6602882Svi117747 /* 6612882Svi117747 * User-Agent = "User-Agent" HCOLON server-val * (LWS server-val) 6622882Svi117747 * servel-val = product |comment 6632882Svi117747 * product = token [SLASH version] 6642882Svi117747 * version = token 6652882Svi117747 */ 6662882Svi117747 int 6672882Svi117747 sip_parse_useragt_header(_sip_header_t *sip_header, 6682882Svi117747 sip_parsed_header_t **header) 6692882Svi117747 { 6702882Svi117747 return (sip_parse_hdr_parser4(sip_header, header)); 6712882Svi117747 } 6722882Svi117747 6732882Svi117747 /* 6742882Svi117747 * Warning = "Warning" HCOLON warning-value *(COMMA warning-value) 6752882Svi117747 * warning-value = warn-code SP warn-agent SP warn-text 6762882Svi117747 * warn-code = 3DIGIT 6772882Svi117747 * warn-agent = hostport | pseudonym ; 6782882Svi117747 * the name or pseudonym of the server adding; 6792882Svi117747 * the Warning header, for use in debugging 6802882Svi117747 * warn-text = quoted-string 6812882Svi117747 * pseudonym = token 6822882Svi117747 */ 6832882Svi117747 int 6842882Svi117747 sip_parse_warn_header(_sip_header_t *sip_header, sip_parsed_header_t **header) 6852882Svi117747 { 6862882Svi117747 sip_parsed_header_t *parsed_header; 6872882Svi117747 int ret; 6882882Svi117747 sip_hdr_value_t *value = NULL; 6892882Svi117747 sip_hdr_value_t *last_value = NULL; 6902882Svi117747 6912882Svi117747 if ((ret = sip_prim_parsers(sip_header, header)) != 0) 6922882Svi117747 return (ret); 6932882Svi117747 6942882Svi117747 if (*header != NULL) 6952882Svi117747 return (0); 6962882Svi117747 6972882Svi117747 parsed_header = calloc(1, sizeof (sip_parsed_header_t)); 6982882Svi117747 if (parsed_header == NULL) 6992882Svi117747 return (ENOMEM); 7002882Svi117747 parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1; 7012882Svi117747 parsed_header->sip_header = sip_header; 7022882Svi117747 7032882Svi117747 while (sip_header->sip_hdr_current < sip_header->sip_hdr_end) { 7042882Svi117747 value = calloc(1, sizeof (sip_hdr_value_t)); 7052882Svi117747 if (value == NULL) { 7062882Svi117747 sip_free_phdr(parsed_header); 7072882Svi117747 return (ENOMEM); 7082882Svi117747 } 7092882Svi117747 7102882Svi117747 if (last_value != NULL) 7112882Svi117747 last_value->sip_next_value = value; 7122882Svi117747 else 7132882Svi117747 parsed_header->value = (sip_value_t *)value; 7142882Svi117747 7152882Svi117747 value->sip_value_start = sip_header->sip_hdr_current; 7162882Svi117747 value->sip_value_header = parsed_header; 7172882Svi117747 7182882Svi117747 ret = sip_atoi(sip_header, &value->warn_code); 7192882Svi117747 if (ret != 0 || value->warn_code < 100 || 7202882Svi117747 value->warn_code > 999) { 7212882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 7222882Svi117747 goto get_next_val; 7232882Svi117747 } 7242882Svi117747 if (sip_skip_white_space(sip_header) != 0) { 7252882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 7262882Svi117747 goto get_next_val; 7272882Svi117747 } 7282882Svi117747 value->warn_agt_ptr = sip_header->sip_hdr_current; 7292882Svi117747 7302882Svi117747 if (sip_find_token(sip_header, SIP_QUOTE) == 0) { 7312882Svi117747 /* 7322882Svi117747 * get warning agent 7332882Svi117747 */ 7342882Svi117747 sip_header->sip_hdr_current--; 7352882Svi117747 (void) sip_reverse_skip_white_space(sip_header); 7362882Svi117747 value->warn_agt_len = sip_header->sip_hdr_current - 7372882Svi117747 value->warn_agt_ptr - 1; 7382882Svi117747 if (value->warn_agt_len <= 0) { 7392882Svi117747 value->warn_agt_ptr = NULL; 7402882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 7412882Svi117747 } 7422882Svi117747 7432882Svi117747 /* 7442882Svi117747 * We will have a SIP_QUOTE here 7452882Svi117747 */ 7462882Svi117747 (void) sip_find_token(sip_header, SIP_QUOTE); 7472882Svi117747 7482882Svi117747 value->warn_text_ptr = sip_header->sip_hdr_current; 7492882Svi117747 if (sip_find_token(sip_header, SIP_QUOTE) == 0) { 7502882Svi117747 value->warn_text_len = 7512882Svi117747 sip_header->sip_hdr_current - 7522882Svi117747 value->warn_text_ptr - 1; 7532882Svi117747 } else { 7542882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 7552882Svi117747 goto get_next_val; 7562882Svi117747 } 7572882Svi117747 } else 7582882Svi117747 /* 7592882Svi117747 * warning text must present 7602882Svi117747 */ 7612882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 7622882Svi117747 7632882Svi117747 get_next_val: 7642882Svi117747 if (sip_find_token(sip_header, SIP_COMMA) != 0) 7652882Svi117747 break; 7662882Svi117747 value->sip_value_end = sip_header->sip_hdr_current - 1; 7672882Svi117747 last_value = value; 7682882Svi117747 (void) sip_skip_white_space(sip_header); 7692882Svi117747 } 7702882Svi117747 7712882Svi117747 *header = parsed_header; 7722882Svi117747 7732882Svi117747 sip_header->sip_hdr_parsed = *header; 7742882Svi117747 return (0); 7752882Svi117747 } 7762882Svi117747 7772882Svi117747 /* 7782882Svi117747 * Parse RAck header 7792882Svi117747 * "RAck" HCOLON response-num LWS CSeq-num LWS Method 7802882Svi117747 * response-num = 1*DIGIT 7812882Svi117747 * CSeq-num = 1*DIGIT 7822882Svi117747 */ 7832882Svi117747 int 7842882Svi117747 sip_parse_rack(_sip_header_t *sip_header, sip_parsed_header_t **header) 7852882Svi117747 { 7862882Svi117747 sip_parsed_header_t *parsed_header; 7872882Svi117747 sip_hdr_value_t *rack_value; 7882882Svi117747 int len; 7892882Svi117747 char *tmp_ptr; 7902882Svi117747 int i; 7912882Svi117747 int ret; 7922882Svi117747 7932882Svi117747 if ((ret = sip_prim_parsers(sip_header, header)) != 0) 7942882Svi117747 return (ret); 7952882Svi117747 7962882Svi117747 if (*header != NULL) 7972882Svi117747 return (0); 7982882Svi117747 7992882Svi117747 parsed_header = calloc(1, sizeof (sip_parsed_header_t)); 8002882Svi117747 if (parsed_header == NULL) 8012882Svi117747 return (ENOMEM); 8022882Svi117747 parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1; 8032882Svi117747 parsed_header->sip_header = sip_header; 8042882Svi117747 8052882Svi117747 parsed_header->value = calloc(1, sizeof (sip_hdr_value_t)); 8062882Svi117747 if (parsed_header->value == NULL) { 8072882Svi117747 free(parsed_header); 8082882Svi117747 return (ENOMEM); 8092882Svi117747 } 8102882Svi117747 rack_value = (sip_hdr_value_t *)parsed_header->value; 8112882Svi117747 rack_value->sip_value_version = SIP_VALUE_VERSION_1; 8122882Svi117747 rack_value->sip_value_start = sip_header->sip_hdr_current; 8132882Svi117747 rack_value->sip_value_header = parsed_header; 8142882Svi117747 if (sip_atoi(sip_header, &rack_value->rack_resp) || 8152882Svi117747 rack_value->rack_resp == 0) { 8162882Svi117747 rack_value->sip_value_state = SIP_VALUE_BAD; 8172882Svi117747 rack_value->sip_value_end = sip_header->sip_hdr_end - 2; 8182882Svi117747 goto rack_parse_done; 8192882Svi117747 } 8202882Svi117747 rack_value->sip_value_header = parsed_header; 8212882Svi117747 /* 8222882Svi117747 * Get cseq. 8232882Svi117747 */ 8242882Svi117747 if (sip_skip_white_space(sip_header) != 0) { 8252882Svi117747 rack_value->sip_value_state = SIP_VALUE_BAD; 8262882Svi117747 rack_value->sip_value_end = sip_header->sip_hdr_end - 2; 8272882Svi117747 goto rack_parse_done; 8282882Svi117747 } 8292882Svi117747 if (sip_atoi(sip_header, &rack_value->rack_cseq)) { 8302882Svi117747 rack_value->sip_value_state = SIP_VALUE_BAD; 8312882Svi117747 rack_value->sip_value_end = sip_header->sip_hdr_end - 2; 8322882Svi117747 goto rack_parse_done; 8332882Svi117747 } 8342882Svi117747 /* 8352882Svi117747 * Get method. 8362882Svi117747 */ 8372882Svi117747 if (sip_skip_white_space(sip_header) != 0) { 8382882Svi117747 rack_value->sip_value_state = SIP_VALUE_BAD; 8392882Svi117747 rack_value->sip_value_end = sip_header->sip_hdr_end - 2; 8402882Svi117747 goto rack_parse_done; 8412882Svi117747 } 8422882Svi117747 8432882Svi117747 tmp_ptr = sip_header->sip_hdr_current; 8442882Svi117747 if (sip_find_white_space(sip_header)) { 8452882Svi117747 rack_value->sip_value_state = SIP_VALUE_BAD; 8462882Svi117747 rack_value->sip_value_end = sip_header->sip_hdr_end - 2; 8472882Svi117747 goto rack_parse_done; 8482882Svi117747 } 8492882Svi117747 8502882Svi117747 len = sip_header->sip_hdr_current - tmp_ptr; 8512882Svi117747 8522882Svi117747 for (i = 1; i < MAX_SIP_METHODS; i++) { 8532882Svi117747 if (strncmp(sip_methods[i].name, tmp_ptr, len) == 0) 8542882Svi117747 break; 8552882Svi117747 } 8562882Svi117747 8572882Svi117747 if (i >= MAX_SIP_METHODS) { 8582882Svi117747 rack_value->sip_value_state = SIP_VALUE_BAD; 8592882Svi117747 rack_value->sip_value_end = sip_header->sip_hdr_end - 2; 8602882Svi117747 goto rack_parse_done; 8612882Svi117747 } 8622882Svi117747 8632882Svi117747 rack_value->rack_method = i; 8642882Svi117747 rack_value->sip_value_end = sip_header->sip_hdr_current; 8652882Svi117747 8662882Svi117747 rack_parse_done: 8672882Svi117747 sip_header->sip_hdr_parsed = parsed_header; 8682882Svi117747 8692882Svi117747 *header = parsed_header; 8702882Svi117747 return (0); 8712882Svi117747 } 8722882Svi117747 8732882Svi117747 /* 8742882Svi117747 * Allow = "Allow" HCOLON [Method *(COMMA Method)] 8752882Svi117747 */ 8762882Svi117747 int 8772882Svi117747 sip_parse_allow_events_header(_sip_header_t *sip_header, 8782882Svi117747 sip_parsed_header_t **header) 8792882Svi117747 { 8802882Svi117747 return (sip_parse_hdr_parser1(sip_header, header, (char)NULL)); 8812882Svi117747 } 8822882Svi117747 8832882Svi117747 /* 8842882Svi117747 * Event = ( "Event" / "o" ) HCOLON event-type 8852882Svi117747 * *( SEMI event-param ) 8862882Svi117747 * event-type = event-package *( "." event-template ) 8872882Svi117747 * event-package = token-nodot 8882882Svi117747 * event-template = token-nodot 8892882Svi117747 * token-nodot = 1*( alphanum / "-" / "!" / "%" / "*" 8902882Svi117747 * / "_" / "+" / "`" / "'" / "~" ) 8912882Svi117747 * event-param = generic-param / ( "id" EQUAL token ) 8922882Svi117747 */ 8932882Svi117747 int 8942882Svi117747 sip_parse_event_header(_sip_header_t *sip_header, sip_parsed_header_t **header) 8952882Svi117747 { 8962882Svi117747 return (sip_parse_hdr_parser1(sip_header, header, (char)NULL)); 8972882Svi117747 } 8982882Svi117747 8992882Svi117747 /* 9002882Svi117747 * Subscription-State = "Subscription-State" HCOLON substate-value 9012882Svi117747 * *( SEMI subexp-params ) 9022882Svi117747 * substate-value = "active" / "pending" / "terminated" 9032882Svi117747 * / extension-substate 9042882Svi117747 * extension-substate = token 9052882Svi117747 * subexp-params = ("reason" EQUAL event-reason-value) 9062882Svi117747 * / ("expires" EQUAL delta-seconds)* 9072882Svi117747 * / ("retry-after" EQUAL delta-seconds) 9082882Svi117747 * / generic-param 9092882Svi117747 * event-reason-value = "deactivated" 9102882Svi117747 * / "probation" 9112882Svi117747 * / "rejected" 9122882Svi117747 * / "timeout" 9132882Svi117747 * / "giveup" 9142882Svi117747 * / "noresource" 9152882Svi117747 * / event-reason-extension 9162882Svi117747 * event-reason-extension = token 9172882Svi117747 */ 9182882Svi117747 int 9192882Svi117747 sip_parse_substate_header(_sip_header_t *sip_header, 9202882Svi117747 sip_parsed_header_t **header) 9212882Svi117747 { 9222882Svi117747 return (sip_parse_hdr_parser1(sip_header, header, (char)NULL)); 9232882Svi117747 } 9242882Svi117747 9252882Svi117747 /* 9262882Svi117747 * Authorization = "Authorization" HCOLON credentials 9272882Svi117747 * credentials = ("Digest" LWS digest-response) 9282882Svi117747 * / other-response 9292882Svi117747 * digest-response = dig-resp *(COMMA dig-resp) 9302882Svi117747 * dig-resp = username / realm / nonce / digest-uri 9312882Svi117747 * / dresponse / algorithm / cnonce 9322882Svi117747 * / opaque / message-qop 9332882Svi117747 * / nonce-count / auth-param 9342882Svi117747 * username = "username" EQUAL username-value 9352882Svi117747 * username-value = quoted-string 9362882Svi117747 * digest-uri = "uri" EQUAL LDQUOT digest-uri-value RDQUOT 9372882Svi117747 * digest-uri-value = rquest-uri ; Equal to request-uri as specified 9382882Svi117747 * by HTTP/1.1 9392882Svi117747 * message-qop = "qop" EQUAL qop-value 9402882Svi117747 * cnonce = "cnonce" EQUAL cnonce-value 9412882Svi117747 * cnonce-value = nonce-value 9422882Svi117747 * nonce-count = "nc" EQUAL nc-value 9432882Svi117747 * nc-value = 8LHEX 9442882Svi117747 * dresponse = "response" EQUAL request-digest 9452882Svi117747 * request-digest = LDQUOT 32LHEX RDQUOT 9462882Svi117747 * auth-param = auth-param-name EQUAL 9472882Svi117747 * ( token / quoted-string ) 9482882Svi117747 * auth-param-name = token 9492882Svi117747 * other-response = auth-scheme LWS auth-param 9502882Svi117747 * *(COMMA auth-param) 9512882Svi117747 * auth-scheme = token 9522882Svi117747 */ 9532882Svi117747 int 9542882Svi117747 sip_parse_author_header(_sip_header_t *sip_header, 9552882Svi117747 sip_parsed_header_t **header) 9562882Svi117747 { 9572882Svi117747 return (sip_parse_hdr_parser5(sip_header, header, B_TRUE)); 9582882Svi117747 } 9592882Svi117747 9602882Svi117747 /* 9612882Svi117747 * Authentication-Info = "Authentication-Info" HCOLON ainfo 9622882Svi117747 * *(COMMA ainfo) 9632882Svi117747 * ainfo = nextnonce / message-qop 9642882Svi117747 * / response-auth / cnonce 9652882Svi117747 * / nonce-count 9662882Svi117747 * nextnonce = "nextnonce" EQUAL nonce-value 9672882Svi117747 * response-auth = "rspauth" EQUAL response-digest 9682882Svi117747 * response-digest = LDQUOT *LHEX RDQUOT 9692882Svi117747 * 9702882Svi117747 */ 9712882Svi117747 int 9722882Svi117747 sip_parse_ainfo_header(_sip_header_t *sip_header, 9732882Svi117747 sip_parsed_header_t **header) 9742882Svi117747 { 9752882Svi117747 return (sip_parse_hdr_parser1(sip_header, header, (char)NULL)); 9762882Svi117747 } 9772882Svi117747 9782882Svi117747 /* 9792882Svi117747 * Proxy-Authenticate = "Proxy-Authenticate" HCOLON challenge 9802882Svi117747 * challenge = ("Digest" LWS digest-cln *(COMMA digest-cln)) 9812882Svi117747 * / other-challenge 9822882Svi117747 * other-challenge = auth-scheme LWS auth-param 9832882Svi117747 * *(COMMA auth-param) 9842882Svi117747 * digest-cln = realm / domain / nonce 9852882Svi117747 * / opaque / stale / algorithm 9862882Svi117747 * / qop-options / auth-param 9872882Svi117747 * realm = "realm" EQUAL realm-value 9882882Svi117747 * realm-value = quoted-string 9892882Svi117747 * domain = "domain" EQUAL LDQUOT URI 9902882Svi117747 * *( 1*SP URI ) RDQUOT 9912882Svi117747 * URI = absoluteURI / abs-path 9922882Svi117747 * nonce = "nonce" EQUAL nonce-value 9932882Svi117747 * nonce-value = quoted-string 9942882Svi117747 * opaque = "opaque" EQUAL quoted-string 9952882Svi117747 * stale = "stale" EQUAL ( "true" / "false" ) 9962882Svi117747 * algorithm = "algorithm" EQUAL ( "MD5" / "MD5-sess" 9972882Svi117747 * / token ) 9982882Svi117747 * qop-options = "qop" EQUAL LDQUOT qop-value 9992882Svi117747 * *("," qop-value) RDQUOT 10002882Svi117747 * qop-value = "auth" / "auth-int" / token 10012882Svi117747 * 10022882Svi117747 */ 10032882Svi117747 int 10042882Svi117747 sip_parse_pauthen_header(_sip_header_t *sip_header, 10052882Svi117747 sip_parsed_header_t **header) 10062882Svi117747 { 10072882Svi117747 return (sip_parse_hdr_parser5(sip_header, header, B_TRUE)); 10082882Svi117747 } 10092882Svi117747 10102882Svi117747 /* 10112882Svi117747 * Proxy-Authorization = "Proxy-Authorization" HCOLON credentials 10122882Svi117747 */ 10132882Svi117747 int 10142882Svi117747 sip_parse_pauthor_header(_sip_header_t *sip_header, 10152882Svi117747 sip_parsed_header_t **header) 10162882Svi117747 { 10172882Svi117747 return (sip_parse_hdr_parser5(sip_header, header, B_TRUE)); 10182882Svi117747 } 10192882Svi117747 10202882Svi117747 /* 10212882Svi117747 * Proxy-Require = "Proxy-Require" HCOLON option-tag 10222882Svi117747 * *(COMMA option-tag) 10232882Svi117747 * option-tag = token 10242882Svi117747 */ 10252882Svi117747 int 10262882Svi117747 sip_parse_preq_header(_sip_header_t *sip_header, 10272882Svi117747 sip_parsed_header_t **header) 10282882Svi117747 { 10292882Svi117747 return (sip_parse_hdr_parser1(sip_header, header, (char)NULL)); 10302882Svi117747 } 10312882Svi117747 10322882Svi117747 /* 10332882Svi117747 * WWW-Authenticate = "WWW-Authenticate" HCOLON challenge 10342882Svi117747 * extension-header = header-name HCOLON header-value 10352882Svi117747 * header-name = token 10362882Svi117747 * header-value = *(TEXT-UTF8char / UTF8-CONT / LWS) 10372882Svi117747 * message-body = *OCTET 10382882Svi117747 * 10392882Svi117747 */ 10402882Svi117747 int 10412882Svi117747 sip_parse_wauthen_header(_sip_header_t *sip_header, 10422882Svi117747 sip_parsed_header_t **header) 10432882Svi117747 { 10442882Svi117747 return (sip_parse_hdr_parser5(sip_header, header, B_TRUE)); 10452882Svi117747 } 10462882Svi117747 10472882Svi117747 /* 10482882Svi117747 * Call-ID = ( "Call-ID" / "i" ) HCOLON callid 10492882Svi117747 */ 10502882Svi117747 int 10512882Svi117747 sip_parse_cid_header(_sip_header_t *sip_header, sip_parsed_header_t **header) 10522882Svi117747 { 10532882Svi117747 return (sip_parse_hdr_parser4(sip_header, header)); 10542882Svi117747 } 10552882Svi117747 10562882Svi117747 /* 10572882Svi117747 * CSeq = "CSeq" HCOLON 1*DIGIT LWS Method 10582882Svi117747 */ 10592882Svi117747 int 10602882Svi117747 sip_parse_cseq_header(_sip_header_t *sip_header, sip_parsed_header_t **header) 10612882Svi117747 { 10622882Svi117747 sip_parsed_header_t *parsed_header; 10632882Svi117747 sip_hdr_value_t *cseq_value; 10642882Svi117747 int len; 10652882Svi117747 char *tmp_ptr; 10662882Svi117747 int i; 10672882Svi117747 int ret; 10682882Svi117747 10692882Svi117747 if ((ret = sip_prim_parsers(sip_header, header)) != 0) 10702882Svi117747 return (ret); 10712882Svi117747 10722882Svi117747 if (*header != NULL) 10732882Svi117747 return (0); 10742882Svi117747 10752882Svi117747 parsed_header = calloc(1, sizeof (sip_parsed_header_t)); 10762882Svi117747 if (parsed_header == NULL) 10772882Svi117747 return (ENOMEM); 10782882Svi117747 parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1; 10792882Svi117747 parsed_header->sip_header = sip_header; 10802882Svi117747 10812882Svi117747 parsed_header->value = calloc(1, sizeof (sip_hdr_value_t)); 10822882Svi117747 if (parsed_header->value == NULL) { 10832882Svi117747 free(parsed_header); 10842882Svi117747 return (ENOMEM); 10852882Svi117747 } 10862882Svi117747 cseq_value = (sip_hdr_value_t *)parsed_header->value; 10872882Svi117747 cseq_value->sip_value_version = SIP_VALUE_VERSION_1; 10882882Svi117747 cseq_value->sip_value_start = sip_header->sip_hdr_current; 10892882Svi117747 if (sip_atoi(sip_header, &cseq_value->cseq_num)) { 10902882Svi117747 cseq_value->sip_value_state = SIP_VALUE_BAD; 10912882Svi117747 cseq_value->sip_value_end = sip_header->sip_hdr_end - 2; 10922882Svi117747 goto cseq_parse_done; 10932882Svi117747 } 10942882Svi117747 cseq_value->sip_value_header = parsed_header; 10952882Svi117747 /* 10962882Svi117747 * Get method. 10972882Svi117747 */ 10982882Svi117747 if (sip_skip_white_space(sip_header) != 0) { 10992882Svi117747 cseq_value->sip_value_state = SIP_VALUE_BAD; 11002882Svi117747 cseq_value->sip_value_end = sip_header->sip_hdr_end - 2; 11012882Svi117747 goto cseq_parse_done; 11022882Svi117747 } 11032882Svi117747 11042882Svi117747 tmp_ptr = sip_header->sip_hdr_current; 11052882Svi117747 11062882Svi117747 if (sip_find_white_space(sip_header)) { 11072882Svi117747 cseq_value->sip_value_state = SIP_VALUE_BAD; 11082882Svi117747 cseq_value->sip_value_end = sip_header->sip_hdr_current; 11092882Svi117747 goto cseq_parse_done; 11102882Svi117747 } 11112882Svi117747 11122882Svi117747 len = sip_header->sip_hdr_current - tmp_ptr; 11132882Svi117747 11142882Svi117747 for (i = 1; i < MAX_SIP_METHODS; i++) { 11152882Svi117747 if (strncmp(sip_methods[i].name, tmp_ptr, len) == 0) 11162882Svi117747 break; 11172882Svi117747 } 11182882Svi117747 11192882Svi117747 if (i >= MAX_SIP_METHODS) { 11202882Svi117747 cseq_value->sip_value_state = SIP_VALUE_BAD; 11212882Svi117747 cseq_value->sip_value_end = sip_header->sip_hdr_current; 11222882Svi117747 goto cseq_parse_done; 11232882Svi117747 } 11242882Svi117747 11252882Svi117747 cseq_value->cseq_method = i; 11262882Svi117747 cseq_value->sip_value_end = sip_header->sip_hdr_current; 11272882Svi117747 cseq_parse_done: 11282882Svi117747 11292882Svi117747 sip_header->sip_hdr_parsed = parsed_header; 11302882Svi117747 11312882Svi117747 *header = parsed_header; 11322882Svi117747 return (0); 11332882Svi117747 } 11342882Svi117747 11352882Svi117747 11362882Svi117747 /* 11372882Svi117747 * Via = ( "Via" / "v" ) HCOLON via-parm *(COMMA via-parm) 11382882Svi117747 * via-parm = sent-protocol LWS sent-by *( SEMI via-params ) 11392882Svi117747 * via-params = via-ttl / via-maddr 11402882Svi117747 * / via-received / via-branch 11412882Svi117747 * / via-extension 11422882Svi117747 * via-ttl = "ttl" EQUAL ttl 11432882Svi117747 * via-maddr = "maddr" EQUAL host 11442882Svi117747 * via-received = "received" EQUAL (IPv4address / IPv6address) 11452882Svi117747 * via-branch = "branch" EQUAL token 11462882Svi117747 * via-extension = generic-param 11472882Svi117747 * sent-protocol = protocol-name SLASH protocol-version 11482882Svi117747 * SLASH transport 11492882Svi117747 * protocol-name = "SIP" / token 11502882Svi117747 * protocol-version = token 11512882Svi117747 * transport = "UDP" / "TCP" / "TLS" / "SCTP" 11522882Svi117747 * / other-transport 11532882Svi117747 * sent-by = host [ COLON port ] 11542882Svi117747 * ttl = 1*3DIGIT ; 0 to 255 11552882Svi117747 * 11562882Svi117747 * There can be multiple via headers we always append the header. 11572882Svi117747 */ 11582882Svi117747 int 11592882Svi117747 sip_parse_via_header(_sip_header_t *sip_header, sip_parsed_header_t **header) 11602882Svi117747 { 11612882Svi117747 sip_parsed_header_t *parsed_header; 11622882Svi117747 int ret; 11632882Svi117747 sip_hdr_value_t *value = NULL; 11642882Svi117747 sip_hdr_value_t *last_value = NULL; 11652882Svi117747 11662882Svi117747 if ((ret = sip_prim_parsers(sip_header, header)) != 0) 11672882Svi117747 return (ret); 11682882Svi117747 11692882Svi117747 if (*header != NULL) 11702882Svi117747 return (0); 11712882Svi117747 11722882Svi117747 parsed_header = calloc(1, sizeof (sip_parsed_header_t)); 11732882Svi117747 if (parsed_header == NULL) 11742882Svi117747 return (ENOMEM); 11752882Svi117747 parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1; 11762882Svi117747 parsed_header->sip_header = sip_header; 11772882Svi117747 11782882Svi117747 while (sip_header->sip_hdr_current < sip_header->sip_hdr_end) { 11792882Svi117747 11802882Svi117747 value = calloc(1, sizeof (sip_hdr_value_t)); 11812882Svi117747 if (value == NULL) { 11822882Svi117747 sip_free_phdr(parsed_header); 11832882Svi117747 return (ENOMEM); 11842882Svi117747 } 11852882Svi117747 if (last_value != NULL) 11862882Svi117747 last_value->sip_next_value = value; 11872882Svi117747 else 11882882Svi117747 parsed_header->value = (sip_value_t *)value; 11892882Svi117747 11902882Svi117747 value->sip_value_version = SIP_VALUE_VERSION_1; 11912882Svi117747 value->sip_value_start = sip_header->sip_hdr_current; 11922882Svi117747 value->sip_value_header = parsed_header; 11932882Svi117747 value->via_protocol_name.sip_str_ptr = 11942882Svi117747 sip_header->sip_hdr_current; 11952882Svi117747 11962882Svi117747 /* 11972882Svi117747 * Check to see if there is a version number 11982882Svi117747 */ 11992882Svi117747 if (sip_get_protocol_version(sip_header, 12002882Svi117747 &value->via_protocol) != 0) { 12012882Svi117747 if (sip_goto_next_value(sip_header) != 0) { 12022882Svi117747 sip_free_phdr(parsed_header); 12032882Svi117747 return (EPROTO); 12042882Svi117747 } 12052882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 12062882Svi117747 goto get_next_via_value; 12072882Svi117747 } 12082882Svi117747 12092882Svi117747 if (sip_find_token(sip_header, SIP_SLASH) != 0) { 12102882Svi117747 if (sip_goto_next_value(sip_header) != 0) { 12112882Svi117747 sip_free_phdr(parsed_header); 12122882Svi117747 return (EPROTO); 12132882Svi117747 } 12142882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 12152882Svi117747 goto get_next_via_value; 12162882Svi117747 } 12172882Svi117747 12182882Svi117747 if (sip_skip_white_space(sip_header) != 0) { 12192882Svi117747 if (sip_goto_next_value(sip_header) != 0) { 12202882Svi117747 sip_free_phdr(parsed_header); 12212882Svi117747 return (EPROTO); 12222882Svi117747 } 12232882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 12242882Svi117747 goto get_next_via_value; 12252882Svi117747 } 12262882Svi117747 12272882Svi117747 value->via_protocol_transport.sip_str_ptr = 12282882Svi117747 sip_header->sip_hdr_current; 12292882Svi117747 if (sip_find_white_space(sip_header) != 0) { 12302882Svi117747 if (sip_goto_next_value(sip_header) != 0) { 12312882Svi117747 sip_free_phdr(parsed_header); 12322882Svi117747 return (EPROTO); 12332882Svi117747 } 12342882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 12352882Svi117747 goto get_next_via_value; 12362882Svi117747 } 12372882Svi117747 12382882Svi117747 value->via_protocol_transport.sip_str_len = 12392882Svi117747 sip_header->sip_hdr_current - 12402882Svi117747 value->via_protocol_transport.sip_str_ptr; 12412882Svi117747 12422882Svi117747 if (sip_skip_white_space(sip_header) != 0) { 12432882Svi117747 if (sip_goto_next_value(sip_header) != 0) { 12442882Svi117747 sip_free_phdr(parsed_header); 12452882Svi117747 return (EPROTO); 12462882Svi117747 } 12472882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 12482882Svi117747 goto get_next_via_value; 12492882Svi117747 } 12502882Svi117747 12512882Svi117747 value->via_sent_by_host.sip_str_ptr = 12522882Svi117747 sip_header->sip_hdr_current; 12532882Svi117747 if (*sip_header->sip_hdr_current == '[') { 12542882Svi117747 if (sip_find_token(sip_header, ']')) { 12552882Svi117747 if (sip_goto_next_value(sip_header) != 0) { 12562882Svi117747 sip_free_phdr(parsed_header); 12572882Svi117747 return (EPROTO); 12582882Svi117747 } 12592882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 12602882Svi117747 goto get_next_via_value; 12612882Svi117747 } 12622882Svi117747 } else if (sip_find_separator(sip_header, SIP_SEMI, SIP_COMMA, 12632882Svi117747 SIP_HCOLON)) { 12642882Svi117747 if (sip_goto_next_value(sip_header) != 0) { 12652882Svi117747 sip_free_phdr(parsed_header); 12662882Svi117747 return (EPROTO); 12672882Svi117747 } 12682882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 12692882Svi117747 goto get_next_via_value; 12702882Svi117747 } 12712882Svi117747 value->via_sent_by_host.sip_str_len = 12722882Svi117747 sip_header->sip_hdr_current - 12732882Svi117747 value->via_sent_by_host.sip_str_ptr; 12742882Svi117747 12752882Svi117747 if (sip_skip_white_space(sip_header) != 0) { 12762882Svi117747 if (sip_goto_next_value(sip_header) != 0) { 12772882Svi117747 sip_free_phdr(parsed_header); 12782882Svi117747 return (EPROTO); 12792882Svi117747 } 12802882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 12812882Svi117747 goto get_next_via_value; 12822882Svi117747 } 12832882Svi117747 12842882Svi117747 if (*sip_header->sip_hdr_current == SIP_HCOLON) { 12852882Svi117747 sip_header->sip_hdr_current++; 12862882Svi117747 /* 12872882Svi117747 * We have a port number 12882882Svi117747 */ 12892882Svi117747 if (sip_atoi(sip_header, &value->via_sent_by_port) != 12902882Svi117747 0) { 12912882Svi117747 if (sip_goto_next_value(sip_header) != 0) { 12922882Svi117747 sip_free_phdr(parsed_header); 12932882Svi117747 return (EPROTO); 12942882Svi117747 } 12952882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 12962882Svi117747 goto get_next_via_value; 12972882Svi117747 } 12982882Svi117747 12992882Svi117747 } 13002882Svi117747 13012882Svi117747 /* 13022882Svi117747 * Do some sanity checking. 13032882Svi117747 * This should be replaced by a v4/v6 address check. 13042882Svi117747 */ 13052882Svi117747 if (value->via_sent_by_host.sip_str_len == 0 || 13062882Svi117747 (!isalnum(*value->via_sent_by_host.sip_str_ptr) && 13072882Svi117747 *value->via_sent_by_host.sip_str_ptr != '[')) { 13082882Svi117747 if (sip_goto_next_value(sip_header) != 0) { 13092882Svi117747 sip_free_phdr(parsed_header); 13102882Svi117747 return (EPROTO); 13112882Svi117747 } 13122882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 13132882Svi117747 goto get_next_via_value; 13142882Svi117747 } 13152882Svi117747 13162882Svi117747 ret = sip_parse_params(sip_header, &value->sip_param_list); 13172882Svi117747 if (ret == EPROTO) { 13182882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 13192882Svi117747 } else if (ret != 0) { 13202882Svi117747 sip_free_phdr(parsed_header); 13212882Svi117747 return (ret); 13222882Svi117747 } 13232882Svi117747 get_next_via_value: 13242882Svi117747 value->sip_value_end = sip_header->sip_hdr_current; 13252882Svi117747 13262882Svi117747 if (sip_find_token(sip_header, SIP_COMMA) != 0) 13272882Svi117747 break; 13282882Svi117747 last_value = value; 13292882Svi117747 (void) sip_skip_white_space(sip_header); 13302882Svi117747 } 13312882Svi117747 13322882Svi117747 sip_header->sip_hdr_parsed = parsed_header; 13332882Svi117747 13342882Svi117747 *header = parsed_header; 13352882Svi117747 return (0); 13362882Svi117747 } 13372882Svi117747 13382882Svi117747 /* 13392882Svi117747 * Max-Forwards = "Max-Forwards" HCOLON 1*DIGIT 13402882Svi117747 */ 13412882Svi117747 int 13422882Svi117747 sip_parse_maxf_header(_sip_header_t *sip_header, sip_parsed_header_t **header) 13432882Svi117747 { 13442882Svi117747 return (sip_parse_hdr_parser2(sip_header, header, SIP_INT_VAL)); 13452882Svi117747 } 13462882Svi117747 13472882Svi117747 /* 13482882Svi117747 * Content-Type = ( "Content-Type" / "c" ) HCOLON media-type 13492882Svi117747 * media-type = m-type SLASH m-subtype *(SEMI m-parameter) 13502882Svi117747 * m-type = discrete-type / composite-type 13512882Svi117747 * discrete-type = "text" / "image" / "audio" / "video" 13522882Svi117747 * / "application" / extension-token 13532882Svi117747 * composite-type = "message" / "multipart" / extension-token 13542882Svi117747 * extension-token = ietf-token / x-token 13552882Svi117747 * ietf-token = token 13562882Svi117747 * x-token = "x-" token 13572882Svi117747 * m-subtype = extension-token / iana-token 13582882Svi117747 * iana-token = token 13592882Svi117747 * m-parameter = m-attribute EQUAL m-value 13602882Svi117747 * m-attribute = token 13612882Svi117747 * m-value = token / quoted-string 13622882Svi117747 */ 13632882Svi117747 int 13642882Svi117747 sip_parse_ctype_header(_sip_header_t *sip_header, sip_parsed_header_t **header) 13652882Svi117747 { 13662882Svi117747 return (sip_parse_hdr_parser1(sip_header, header, SIP_SLASH)); 13672882Svi117747 } 13682882Svi117747 13692882Svi117747 /* 13702882Svi117747 * Content-Length = ( "Content-Length" / "l" ) HCOLON 1*DIGIT 13712882Svi117747 */ 13722882Svi117747 int 13732882Svi117747 sip_parse_clen_header(_sip_header_t *sip_header, sip_parsed_header_t **header) 13742882Svi117747 { 13752882Svi117747 return (sip_parse_hdr_parser2(sip_header, header, SIP_INT_VAL)); 13762882Svi117747 } 13772882Svi117747 13782882Svi117747 /* 13792882Svi117747 * Generic parser for Contact, From, To, Route and Record-Route headers 13802882Svi117747 * 13812882Svi117747 * Contact = ("Contact" / "m" ) HCOLON 13822882Svi117747 * ( STAR / (contact-param *(COMMA contact-param))) 13832882Svi117747 * contact-param = (name-addr / addr-spec) *(SEMI contact-params) 13842882Svi117747 * name-addr = [ display-name ] LAQUOT addr-spec RAQUOT 13852882Svi117747 * addr-spec = SIP-URI / SIPS-URI / absoluteURI 13862882Svi117747 * display-name = *(token LWS)/ quoted-string 13872882Svi117747 * contact-params = c-p-q / c-p-expires 13882882Svi117747 * / contact-extension 13892882Svi117747 * 13902882Svi117747 * From = ( "From" / "f" ) HCOLON from-spec 13912882Svi117747 * from-spec = ( name-addr / addr-spec ) 13922882Svi117747 * *( SEMI from-param ) 13932882Svi117747 * from-param = tag-param / generic-param 13942882Svi117747 * tag-param = "tag" EQUAL token 13952882Svi117747 * 13962882Svi117747 * To = ( "To" / "t" ) HCOLON ( name-addr 13972882Svi117747 * / addr-spec ) *( SEMI to-param ) 13982882Svi117747 * to-param = tag-param / generic-param 13992882Svi117747 * 14002882Svi117747 * Route = "Route" HCOLON route-param *(COMMA route-param) 14012882Svi117747 * route-param = name-addr *( SEMI rr-param ) 14022882Svi117747 * 14032882Svi117747 * Record-Route = "Record-Route" HCOLON rec-route *(COMMA rec-route) 14042882Svi117747 * rec-route = name-addr *( SEMI rr-param ) 14052882Svi117747 * rr-param = generic-param 14062882Svi117747 * 14072882Svi117747 * We could have multiple values for these headers. For the ones that have 14082882Svi117747 * a display name we will have a LAQUOT/RAQUOT. If we encounter an error 14092882Svi117747 * when parsing a value, we mark the value as bad and start paring the 14102882Svi117747 * next value, if present. Before we start parsing the next value, we 14112882Svi117747 * check for any parameters, if present. 14122882Svi117747 */ 14132882Svi117747 int 14142882Svi117747 sip_parse_cftr_header(_sip_header_t *sip_header, sip_parsed_header_t **header) 14152882Svi117747 { 14162882Svi117747 sip_parsed_header_t *parsed_header; 14172882Svi117747 char *tmp_ptr; 14182882Svi117747 char *tmp_ptr_2; 14192882Svi117747 int ret; 14202882Svi117747 sip_hdr_value_t *value = NULL; 14212882Svi117747 sip_hdr_value_t *last_value = NULL; 14222882Svi117747 14232882Svi117747 if ((ret = sip_prim_parsers(sip_header, header)) != 0) 14242882Svi117747 return (ret); 14252882Svi117747 14262882Svi117747 if (*header != NULL) 14272882Svi117747 return (0); 14282882Svi117747 14292882Svi117747 parsed_header = calloc(1, sizeof (sip_parsed_header_t)); 14302882Svi117747 if (parsed_header == NULL) 14312882Svi117747 return (ENOMEM); 14322882Svi117747 parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1; 14332882Svi117747 parsed_header->sip_header = sip_header; 14342882Svi117747 while (sip_header->sip_hdr_current < sip_header->sip_hdr_end) { 14352882Svi117747 boolean_t quoted_name = B_FALSE; 14362882Svi117747 14372882Svi117747 value = calloc(1, sizeof (sip_hdr_value_t)); 14382882Svi117747 if (value == NULL) { 14392882Svi117747 sip_free_cftr_header(parsed_header); 14402882Svi117747 return (ENOMEM); 14412882Svi117747 } 14422882Svi117747 if (last_value != NULL) 14432882Svi117747 last_value->sip_next_value = value; 14442882Svi117747 else 14452882Svi117747 parsed_header->value = (sip_value_t *)value; 14462882Svi117747 if (*sip_header->sip_hdr_current == SIP_QUOTE) { 14472882Svi117747 sip_header->sip_hdr_current++; 14482882Svi117747 quoted_name = B_TRUE; 14492882Svi117747 } 14502882Svi117747 value->sip_value_version = SIP_VALUE_VERSION_1; 14512882Svi117747 value->sip_value_start = sip_header->sip_hdr_current; 14522882Svi117747 value->sip_value_header = parsed_header; 14532882Svi117747 /* 14542882Svi117747 * let's see if there is a display name 14552882Svi117747 */ 14562882Svi117747 if (*sip_header->sip_hdr_current != SIP_LAQUOT) { 14572882Svi117747 14582882Svi117747 tmp_ptr = sip_header->sip_hdr_current; 14592882Svi117747 /* 14602882Svi117747 * According to 20.10 '<' may not have a leading 14612882Svi117747 * space. 14622882Svi117747 */ 14632882Svi117747 if (quoted_name && 14642882Svi117747 sip_find_token(sip_header, SIP_QUOTE) != 0) { 14652882Svi117747 if (sip_goto_next_value(sip_header) != 0) { 14662882Svi117747 sip_free_cftr_header(parsed_header); 14672882Svi117747 return (EPROTO); 14682882Svi117747 } 14692882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 14702882Svi117747 goto get_next_cftr_value; 14712882Svi117747 } else if (sip_find_separator(sip_header, SIP_SEMI, 14722882Svi117747 SIP_LAQUOT, SIP_COMMA) != 0) { 14732882Svi117747 /* 14742882Svi117747 * only a uri. 14752882Svi117747 */ 14762882Svi117747 value->cftr_uri.sip_str_ptr = tmp_ptr; 14772882Svi117747 value->cftr_uri.sip_str_len = 14782882Svi117747 sip_header->sip_hdr_current - tmp_ptr; 14792882Svi117747 /* 14802882Svi117747 * It's an error not to have a uri. 14812882Svi117747 */ 14822882Svi117747 if (value->cftr_uri.sip_str_len == 0) { 14832882Svi117747 if (sip_goto_next_value(sip_header) != 14842882Svi117747 0) { 14852882Svi117747 sip_free_cftr_header( 14862882Svi117747 parsed_header); 14872882Svi117747 return (EPROTO); 14882882Svi117747 } 14892882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 14902882Svi117747 goto get_next_cftr_value; 14912882Svi117747 } 14922882Svi117747 continue; 14932882Svi117747 } 14942882Svi117747 14952882Svi117747 tmp_ptr_2 = sip_header->sip_hdr_current; 14962882Svi117747 if (*sip_header->sip_hdr_current == SIP_SP) { 14972882Svi117747 if (sip_skip_white_space(sip_header) != 0) { 14982882Svi117747 /* 14992882Svi117747 * only a uri. 15002882Svi117747 */ 15012882Svi117747 value->cftr_uri.sip_str_ptr = tmp_ptr; 15022882Svi117747 value->cftr_uri.sip_str_len = 15032882Svi117747 tmp_ptr_2 - tmp_ptr; 15042882Svi117747 /* 15052882Svi117747 * It's an error not to have a uri. 15062882Svi117747 */ 15072882Svi117747 if (value->cftr_uri.sip_str_len == 0) { 15082882Svi117747 if (sip_goto_next_value( 15092882Svi117747 sip_header) != 0) { 15102882Svi117747 sip_free_cftr_header( 15112882Svi117747 parsed_header); 15122882Svi117747 return (EPROTO); 15132882Svi117747 } 15142882Svi117747 value->sip_value_state = 15152882Svi117747 SIP_VALUE_BAD; 15162882Svi117747 goto get_next_cftr_value; 15172882Svi117747 } 15182882Svi117747 continue; 15192882Svi117747 } 15202882Svi117747 } 15212882Svi117747 15222882Svi117747 if (*sip_header->sip_hdr_current != SIP_LAQUOT) { 15232882Svi117747 /* 15242882Svi117747 * No display name here. 15252882Svi117747 */ 15262882Svi117747 value->cftr_uri.sip_str_ptr = tmp_ptr; 15272882Svi117747 value->cftr_uri.sip_str_len = tmp_ptr_2 - 15282882Svi117747 tmp_ptr; 15292882Svi117747 /* 15302882Svi117747 * It's an error not to have a uri. 15312882Svi117747 */ 15322882Svi117747 if (value->cftr_uri.sip_str_len == 0) { 15332882Svi117747 if (sip_goto_next_value(sip_header) != 15342882Svi117747 0) { 15352882Svi117747 sip_free_cftr_header( 15362882Svi117747 parsed_header); 15372882Svi117747 return (EPROTO); 15382882Svi117747 } 15392882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 15402882Svi117747 goto get_next_cftr_value; 15412882Svi117747 } 15422882Svi117747 goto get_params; 15432882Svi117747 } 15442882Svi117747 15452882Svi117747 value->cftr_name = malloc(sizeof (sip_str_t)); 15462882Svi117747 if (value->cftr_name == NULL) { 15472882Svi117747 sip_free_cftr_header(parsed_header); 15482882Svi117747 return (ENOMEM); 15492882Svi117747 } 15502882Svi117747 value->cftr_name->sip_str_ptr = tmp_ptr; 15512882Svi117747 value->cftr_name->sip_str_len = tmp_ptr_2 - tmp_ptr; 15522882Svi117747 if (quoted_name) 15532882Svi117747 value->cftr_name->sip_str_len--; 15542882Svi117747 } 15552882Svi117747 15562882Svi117747 if (sip_find_token(sip_header, SIP_LAQUOT) != 0) { 15572882Svi117747 if (sip_goto_next_value(sip_header) != 0) { 15582882Svi117747 sip_free_cftr_header(parsed_header); 15592882Svi117747 return (EPROTO); 15602882Svi117747 } 15612882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 15622882Svi117747 goto get_next_cftr_value; 15632882Svi117747 } 15642882Svi117747 15652882Svi117747 if (*sip_header->sip_hdr_current == SIP_SP) { 15662882Svi117747 if (sip_skip_white_space(sip_header) != 0) { 15672882Svi117747 if (sip_goto_next_value(sip_header) != 0) { 15682882Svi117747 sip_free_cftr_header(parsed_header); 15692882Svi117747 return (EPROTO); 15702882Svi117747 } 15712882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 15722882Svi117747 goto get_next_cftr_value; 15732882Svi117747 } 15742882Svi117747 } 15752882Svi117747 15762882Svi117747 tmp_ptr = sip_header->sip_hdr_current; 15772882Svi117747 15782882Svi117747 if (sip_find_separator(sip_header, SIP_RAQUOT, (char)NULL, 15792882Svi117747 (char)NULL)) { 15802882Svi117747 if (sip_goto_next_value(sip_header) != 0) { 15812882Svi117747 sip_free_cftr_header(parsed_header); 15822882Svi117747 return (EPROTO); 15832882Svi117747 } 15842882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 15852882Svi117747 goto get_next_cftr_value; 15862882Svi117747 } 15872882Svi117747 15882882Svi117747 value->cftr_uri.sip_str_ptr = tmp_ptr; 15892882Svi117747 value->cftr_uri.sip_str_len = 15902882Svi117747 sip_header->sip_hdr_current - tmp_ptr; 15912882Svi117747 15922882Svi117747 if (sip_find_token(sip_header, SIP_RAQUOT) != 0) { 15932882Svi117747 if (sip_goto_next_value(sip_header) != 0) { 15942882Svi117747 sip_free_cftr_header(parsed_header); 15952882Svi117747 return (EINVAL); 15962882Svi117747 } 15972882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 15982882Svi117747 goto get_next_cftr_value; 15992882Svi117747 } 16002882Svi117747 16012882Svi117747 if (value->cftr_uri.sip_str_len <= strlen("<>")) { 16022882Svi117747 if (sip_goto_next_value(sip_header) != 0) { 16032882Svi117747 sip_free_cftr_header(parsed_header); 16042882Svi117747 return (EPROTO); 16052882Svi117747 } 16062882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 16072882Svi117747 goto get_next_cftr_value; 16082882Svi117747 } 16092882Svi117747 16102882Svi117747 get_params: 16112882Svi117747 ret = sip_parse_params(sip_header, &value->sip_param_list); 16122882Svi117747 if (ret == EPROTO) { 16132882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 16142882Svi117747 } else if (ret != 0) { 16152882Svi117747 sip_free_cftr_header(parsed_header); 16162882Svi117747 return (ret); 16172882Svi117747 } 16182882Svi117747 get_next_cftr_value: 16192882Svi117747 value->sip_value_end = sip_header->sip_hdr_current; 16202882Svi117747 16212882Svi117747 /* 16222882Svi117747 * Parse uri 16232882Svi117747 */ 16242882Svi117747 if (value->cftr_uri.sip_str_len > 0) { 16252882Svi117747 int error; 16262882Svi117747 16272882Svi117747 value->sip_value_parsed_uri = sip_parse_uri( 16282882Svi117747 &value->cftr_uri, &error); 16292882Svi117747 if (value->sip_value_parsed_uri == NULL) { 16302882Svi117747 sip_free_cftr_header(parsed_header); 16312882Svi117747 return (ENOMEM); 16322882Svi117747 } 16332882Svi117747 if (error != 0 || 16342882Svi117747 ((_sip_uri_t *)value->sip_value_parsed_uri)-> 16352882Svi117747 sip_uri_errflags != 0) { 16362882Svi117747 value->sip_value_state = SIP_VALUE_BAD; 16372882Svi117747 } 16382882Svi117747 } 16392882Svi117747 16402882Svi117747 (void) sip_find_token(sip_header, SIP_COMMA); 16412882Svi117747 last_value = value; 16422882Svi117747 (void) sip_skip_white_space(sip_header); 16432882Svi117747 } 16442882Svi117747 16452882Svi117747 sip_header->sip_hdr_parsed = parsed_header; 16462882Svi117747 16472882Svi117747 *header = parsed_header; 16482882Svi117747 return (0); 16492882Svi117747 } 16502882Svi117747 16512882Svi117747 /* 16522882Svi117747 * PAssertedID = "P-Asserted-Identity" HCOLON PAssertedID-value 16532882Svi117747 * *(COMMA PAssertedID-value) 16542882Svi117747 * PAssertedID-value = name-addr / addr-spec 16552882Svi117747 */ 16562882Svi117747 int 16572882Svi117747 sip_parse_passertedid(_sip_header_t *sip_header, sip_parsed_header_t **header) 16582882Svi117747 { 16592882Svi117747 return (sip_parse_hdr_parser3(sip_header, header, SIP_STRS_VAL, 16602882Svi117747 B_TRUE)); 16612882Svi117747 } 16622882Svi117747 16632882Svi117747 /* 16642882Svi117747 * PPreferredID = "P-Preferred-Identity" HCOLON PPreferredID-value 16652882Svi117747 * *(COMMA PAssertedID-value) 16662882Svi117747 * PPreferredID-value = name-addr / addr-spec 16672882Svi117747 */ 16682882Svi117747 int 16692882Svi117747 sip_parse_ppreferredid(_sip_header_t *sip_header, sip_parsed_header_t **header) 16702882Svi117747 { 16712882Svi117747 return (sip_parse_hdr_parser3(sip_header, header, SIP_STRS_VAL, 16722882Svi117747 B_TRUE)); 16732882Svi117747 } 16742882Svi117747 16752882Svi117747 16762882Svi117747 /* 16772882Svi117747 * We don't do anything for a header we don't understand 16782882Svi117747 */ 16792882Svi117747 /* ARGSUSED */ 16802882Svi117747 int 16812882Svi117747 sip_parse_unknown_header(_sip_header_t *sip_header, 16822882Svi117747 sip_parsed_header_t **header) 16832882Svi117747 { 16842882Svi117747 return (EINVAL); 16852882Svi117747 } 1686