1*a93a1f58Sgm209912 /* 2*a93a1f58Sgm209912 * CDDL HEADER START 3*a93a1f58Sgm209912 * 4*a93a1f58Sgm209912 * The contents of this file are subject to the terms of the 5*a93a1f58Sgm209912 * Common Development and Distribution License (the "License"). 6*a93a1f58Sgm209912 * You may not use this file except in compliance with the License. 7*a93a1f58Sgm209912 * 8*a93a1f58Sgm209912 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*a93a1f58Sgm209912 * or http://www.opensolaris.org/os/licensing. 10*a93a1f58Sgm209912 * See the License for the specific language governing permissions 11*a93a1f58Sgm209912 * and limitations under the License. 12*a93a1f58Sgm209912 * 13*a93a1f58Sgm209912 * When distributing Covered Code, include this CDDL HEADER in each 14*a93a1f58Sgm209912 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*a93a1f58Sgm209912 * If applicable, add the following below this CDDL HEADER, with the 16*a93a1f58Sgm209912 * fields enclosed by brackets "[]" replaced with your own identifying 17*a93a1f58Sgm209912 * information: Portions Copyright [yyyy] [name of copyright owner] 18*a93a1f58Sgm209912 * 19*a93a1f58Sgm209912 * CDDL HEADER END 20*a93a1f58Sgm209912 */ 21*a93a1f58Sgm209912 22*a93a1f58Sgm209912 /* 23*a93a1f58Sgm209912 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24*a93a1f58Sgm209912 * Use is subject to license terms. 25*a93a1f58Sgm209912 */ 26*a93a1f58Sgm209912 27*a93a1f58Sgm209912 #pragma ident "%Z%%M% %I% %E% SMI" 28*a93a1f58Sgm209912 29*a93a1f58Sgm209912 /* 30*a93a1f58Sgm209912 * Parses the SDP description as per the SDP grammar defined in Section 9 of 31*a93a1f58Sgm209912 * RFC 4566 32*a93a1f58Sgm209912 */ 33*a93a1f58Sgm209912 34*a93a1f58Sgm209912 #include <errno.h> 35*a93a1f58Sgm209912 #include <stdlib.h> 36*a93a1f58Sgm209912 #include <string.h> 37*a93a1f58Sgm209912 #include <ctype.h> 38*a93a1f58Sgm209912 #include <sdp.h> 39*a93a1f58Sgm209912 40*a93a1f58Sgm209912 #include "sdp_parse.h" 41*a93a1f58Sgm209912 #include "commp_util.h" 42*a93a1f58Sgm209912 43*a93a1f58Sgm209912 /* 44*a93a1f58Sgm209912 * proto-version-field (v=) 45*a93a1f58Sgm209912 * %x76 "=" 1*DIGIT CRLF 46*a93a1f58Sgm209912 */ 47*a93a1f58Sgm209912 static void 48*a93a1f58Sgm209912 sdp_parse_version(int *version, const char *begin, const char *end, 49*a93a1f58Sgm209912 uint_t *p_error) 50*a93a1f58Sgm209912 { 51*a93a1f58Sgm209912 if (*begin++ != COMMP_EQUALS || commp_atoi(begin, end, version) != 0) 52*a93a1f58Sgm209912 *p_error |= SDP_VERSION_ERROR; 53*a93a1f58Sgm209912 } 54*a93a1f58Sgm209912 55*a93a1f58Sgm209912 /* 56*a93a1f58Sgm209912 * session-name-field (s=) 57*a93a1f58Sgm209912 * %x73 "=" text CRLF 58*a93a1f58Sgm209912 * text = byte-string 59*a93a1f58Sgm209912 * byte-string = 1*(%x01-09/%x0B-0C/%x0E-FF) 60*a93a1f58Sgm209912 * ;any byte except NUL, CR, or LF 61*a93a1f58Sgm209912 */ 62*a93a1f58Sgm209912 static void 63*a93a1f58Sgm209912 sdp_parse_name(char **name, const char *begin, const char *end, 64*a93a1f58Sgm209912 uint_t *p_error) 65*a93a1f58Sgm209912 { 66*a93a1f58Sgm209912 int len; 67*a93a1f58Sgm209912 68*a93a1f58Sgm209912 if (*begin++ != COMMP_EQUALS) { 69*a93a1f58Sgm209912 *p_error |= SDP_NAME_ERROR; 70*a93a1f58Sgm209912 return; 71*a93a1f58Sgm209912 } 72*a93a1f58Sgm209912 /* there can be only one name field */ 73*a93a1f58Sgm209912 if (*name != NULL) 74*a93a1f58Sgm209912 return; 75*a93a1f58Sgm209912 len = end - begin; 76*a93a1f58Sgm209912 if (len < 1) { 77*a93a1f58Sgm209912 *p_error |= SDP_NAME_ERROR; 78*a93a1f58Sgm209912 } else { 79*a93a1f58Sgm209912 COMMP_COPY_STR(*name, begin, len); 80*a93a1f58Sgm209912 if (*name == NULL) { 81*a93a1f58Sgm209912 *p_error |= SDP_MEMORY_ERROR; 82*a93a1f58Sgm209912 return; 83*a93a1f58Sgm209912 } 84*a93a1f58Sgm209912 } 85*a93a1f58Sgm209912 } 86*a93a1f58Sgm209912 87*a93a1f58Sgm209912 /* 88*a93a1f58Sgm209912 * information-field (i=) 89*a93a1f58Sgm209912 * [%x69 "=" text CRLF] 90*a93a1f58Sgm209912 * text = byte-string 91*a93a1f58Sgm209912 * byte-string = 1*(%x01-09/%x0B-0C/%x0E-FF) 92*a93a1f58Sgm209912 * any byte except NUL, CR, or LF 93*a93a1f58Sgm209912 */ 94*a93a1f58Sgm209912 static void 95*a93a1f58Sgm209912 sdp_parse_info(char **info, const char *begin, const char *end, 96*a93a1f58Sgm209912 uint_t *p_error) 97*a93a1f58Sgm209912 { 98*a93a1f58Sgm209912 int len; 99*a93a1f58Sgm209912 100*a93a1f58Sgm209912 if (*begin++ != COMMP_EQUALS) { 101*a93a1f58Sgm209912 *p_error |= SDP_INFO_ERROR; 102*a93a1f58Sgm209912 return; 103*a93a1f58Sgm209912 } 104*a93a1f58Sgm209912 /* There can be only one info field */ 105*a93a1f58Sgm209912 if (*info != NULL) 106*a93a1f58Sgm209912 return; 107*a93a1f58Sgm209912 len = end - begin; 108*a93a1f58Sgm209912 if (len < 1) { 109*a93a1f58Sgm209912 *p_error |= SDP_INFO_ERROR; 110*a93a1f58Sgm209912 } else { 111*a93a1f58Sgm209912 COMMP_COPY_STR(*info, begin, len); 112*a93a1f58Sgm209912 if (*info == NULL) { 113*a93a1f58Sgm209912 *p_error |= SDP_MEMORY_ERROR; 114*a93a1f58Sgm209912 return; 115*a93a1f58Sgm209912 } 116*a93a1f58Sgm209912 } 117*a93a1f58Sgm209912 } 118*a93a1f58Sgm209912 119*a93a1f58Sgm209912 /* 120*a93a1f58Sgm209912 * uri-field (u=) 121*a93a1f58Sgm209912 * [%x75 "=" uri CRLF] 122*a93a1f58Sgm209912 * anything between "=" and "CRLF" is considered to be URI. 123*a93a1f58Sgm209912 */ 124*a93a1f58Sgm209912 static void 125*a93a1f58Sgm209912 sdp_parse_uri(char **uri, const char *begin, const char *end, uint_t *p_error) 126*a93a1f58Sgm209912 { 127*a93a1f58Sgm209912 int len; 128*a93a1f58Sgm209912 129*a93a1f58Sgm209912 if (*begin++ != COMMP_EQUALS) { 130*a93a1f58Sgm209912 *p_error |= SDP_URI_ERROR; 131*a93a1f58Sgm209912 return; 132*a93a1f58Sgm209912 } 133*a93a1f58Sgm209912 /* There can be only one uri field */ 134*a93a1f58Sgm209912 if (*uri != NULL) 135*a93a1f58Sgm209912 return; 136*a93a1f58Sgm209912 len = end - begin; 137*a93a1f58Sgm209912 if (len < 1 || isspace(*begin) || isspace (*(end - 1))) { 138*a93a1f58Sgm209912 *p_error |= SDP_URI_ERROR; 139*a93a1f58Sgm209912 } else { 140*a93a1f58Sgm209912 COMMP_COPY_STR(*uri, begin, len); 141*a93a1f58Sgm209912 if (*uri == NULL) { 142*a93a1f58Sgm209912 *p_error |= SDP_MEMORY_ERROR; 143*a93a1f58Sgm209912 return; 144*a93a1f58Sgm209912 } 145*a93a1f58Sgm209912 } 146*a93a1f58Sgm209912 } 147*a93a1f58Sgm209912 148*a93a1f58Sgm209912 /* 149*a93a1f58Sgm209912 * phone-fields (p=) 150*a93a1f58Sgm209912 * *(%x70 "=" phone-number CRLF) 151*a93a1f58Sgm209912 * anything between "=" and "CRLF" is considered to be phone-number 152*a93a1f58Sgm209912 */ 153*a93a1f58Sgm209912 static void 154*a93a1f58Sgm209912 sdp_parse_phone(sdp_list_t **phone, const char *begin, const char *end, 155*a93a1f58Sgm209912 uint_t *p_error) 156*a93a1f58Sgm209912 { 157*a93a1f58Sgm209912 int len; 158*a93a1f58Sgm209912 sdp_list_t *new_phone = NULL; 159*a93a1f58Sgm209912 sdp_list_t *tmp = NULL; 160*a93a1f58Sgm209912 161*a93a1f58Sgm209912 if (*begin++ != COMMP_EQUALS) { 162*a93a1f58Sgm209912 *p_error |= SDP_PHONE_ERROR; 163*a93a1f58Sgm209912 return; 164*a93a1f58Sgm209912 } 165*a93a1f58Sgm209912 len = end - begin; 166*a93a1f58Sgm209912 if (len < 1 || isspace(*begin) || isspace(*(end - 1))) { 167*a93a1f58Sgm209912 *p_error |= SDP_PHONE_ERROR; 168*a93a1f58Sgm209912 } else { 169*a93a1f58Sgm209912 new_phone = calloc(1, sizeof (sdp_list_t)); 170*a93a1f58Sgm209912 if (new_phone == NULL) { 171*a93a1f58Sgm209912 *p_error |= SDP_MEMORY_ERROR; 172*a93a1f58Sgm209912 return; 173*a93a1f58Sgm209912 } 174*a93a1f58Sgm209912 COMMP_COPY_STR(new_phone->value, begin, len); 175*a93a1f58Sgm209912 if (new_phone->value == NULL) { 176*a93a1f58Sgm209912 free(new_phone); 177*a93a1f58Sgm209912 *p_error |= SDP_MEMORY_ERROR; 178*a93a1f58Sgm209912 return; 179*a93a1f58Sgm209912 } 180*a93a1f58Sgm209912 if (*phone == NULL) { 181*a93a1f58Sgm209912 *phone = new_phone; 182*a93a1f58Sgm209912 } else { 183*a93a1f58Sgm209912 tmp = *phone; 184*a93a1f58Sgm209912 while (tmp->next != NULL) 185*a93a1f58Sgm209912 tmp = tmp->next; 186*a93a1f58Sgm209912 tmp->next = new_phone; 187*a93a1f58Sgm209912 } 188*a93a1f58Sgm209912 } 189*a93a1f58Sgm209912 } 190*a93a1f58Sgm209912 191*a93a1f58Sgm209912 /* 192*a93a1f58Sgm209912 * email-fields (e=) 193*a93a1f58Sgm209912 * *(%x65 "=" email-address CRLF) 194*a93a1f58Sgm209912 * anything between "=" and "CRLF" is considered to be email-address 195*a93a1f58Sgm209912 */ 196*a93a1f58Sgm209912 static void 197*a93a1f58Sgm209912 sdp_parse_email(sdp_list_t **email, const char *begin, const char *end, 198*a93a1f58Sgm209912 uint_t *p_error) 199*a93a1f58Sgm209912 { 200*a93a1f58Sgm209912 int len; 201*a93a1f58Sgm209912 sdp_list_t *new_email = NULL; 202*a93a1f58Sgm209912 sdp_list_t *tmp = NULL; 203*a93a1f58Sgm209912 204*a93a1f58Sgm209912 if (*begin++ != COMMP_EQUALS) { 205*a93a1f58Sgm209912 *p_error |= SDP_EMAIL_ERROR; 206*a93a1f58Sgm209912 return; 207*a93a1f58Sgm209912 } 208*a93a1f58Sgm209912 len = end - begin; 209*a93a1f58Sgm209912 if (len < 1 || isspace(*begin) || isspace(*(end - 1))) { 210*a93a1f58Sgm209912 *p_error |= SDP_EMAIL_ERROR; 211*a93a1f58Sgm209912 } else { 212*a93a1f58Sgm209912 new_email = calloc(1, sizeof (sdp_list_t)); 213*a93a1f58Sgm209912 if (new_email == NULL) { 214*a93a1f58Sgm209912 *p_error |= SDP_MEMORY_ERROR; 215*a93a1f58Sgm209912 return; 216*a93a1f58Sgm209912 } 217*a93a1f58Sgm209912 COMMP_COPY_STR(new_email->value, begin, len); 218*a93a1f58Sgm209912 if (new_email->value == NULL) { 219*a93a1f58Sgm209912 free(new_email); 220*a93a1f58Sgm209912 *p_error |= SDP_MEMORY_ERROR; 221*a93a1f58Sgm209912 return; 222*a93a1f58Sgm209912 } 223*a93a1f58Sgm209912 if (*email == NULL) { 224*a93a1f58Sgm209912 *email = new_email; 225*a93a1f58Sgm209912 } else { 226*a93a1f58Sgm209912 tmp = *email; 227*a93a1f58Sgm209912 while (tmp->next != NULL) 228*a93a1f58Sgm209912 tmp = tmp->next; 229*a93a1f58Sgm209912 tmp->next = new_email; 230*a93a1f58Sgm209912 } 231*a93a1f58Sgm209912 } 232*a93a1f58Sgm209912 } 233*a93a1f58Sgm209912 234*a93a1f58Sgm209912 /* 235*a93a1f58Sgm209912 * origin-field (o=) 236*a93a1f58Sgm209912 * %x6f "=" username SP sess-id SP sess-version SP nettype SP addrtype SP 237*a93a1f58Sgm209912 * unicast-address CRLF 238*a93a1f58Sgm209912 * 239*a93a1f58Sgm209912 * username = non-ws-string 240*a93a1f58Sgm209912 * sess-id = 1*DIGIT 241*a93a1f58Sgm209912 * sess-version = 1*DIGIT 242*a93a1f58Sgm209912 * nettype = token 243*a93a1f58Sgm209912 * addrtype = token 244*a93a1f58Sgm209912 * token = 1*(token-char) 245*a93a1f58Sgm209912 * token-char = %x21 / %x23-27 / %x2A-2B / %x2D-2E / %x30-39 / %x41-5A / %x5E-7E 246*a93a1f58Sgm209912 * i.e. no space in token-char 247*a93a1f58Sgm209912 */ 248*a93a1f58Sgm209912 static void 249*a93a1f58Sgm209912 sdp_parse_origin(sdp_origin_t **origin, const char *begin, const char *end, 250*a93a1f58Sgm209912 uint_t *p_error) 251*a93a1f58Sgm209912 { 252*a93a1f58Sgm209912 const char *current = NULL; 253*a93a1f58Sgm209912 sdp_origin_t *new_origin = NULL; 254*a93a1f58Sgm209912 255*a93a1f58Sgm209912 if (*begin++ != COMMP_EQUALS) { 256*a93a1f58Sgm209912 *p_error |= SDP_ORIGIN_ERROR; 257*a93a1f58Sgm209912 return; 258*a93a1f58Sgm209912 } 259*a93a1f58Sgm209912 /* There can be only one origin field */ 260*a93a1f58Sgm209912 if (*origin != NULL) 261*a93a1f58Sgm209912 return; 262*a93a1f58Sgm209912 new_origin = calloc(1, sizeof (sdp_origin_t)); 263*a93a1f58Sgm209912 if (new_origin == NULL) { 264*a93a1f58Sgm209912 *p_error |= SDP_MEMORY_ERROR; 265*a93a1f58Sgm209912 return; 266*a93a1f58Sgm209912 } 267*a93a1f58Sgm209912 /* Get username */ 268*a93a1f58Sgm209912 current = begin; 269*a93a1f58Sgm209912 if (commp_find_token(&begin, ¤t, end, COMMP_SP, B_FALSE) != 0) { 270*a93a1f58Sgm209912 goto err_ret; 271*a93a1f58Sgm209912 } else { 272*a93a1f58Sgm209912 COMMP_COPY_STR(new_origin->o_username, begin, current - begin); 273*a93a1f58Sgm209912 if (new_origin->o_username == NULL) { 274*a93a1f58Sgm209912 sdp_free_origin(new_origin); 275*a93a1f58Sgm209912 *p_error |= SDP_MEMORY_ERROR; 276*a93a1f58Sgm209912 return; 277*a93a1f58Sgm209912 } 278*a93a1f58Sgm209912 } 279*a93a1f58Sgm209912 /* Get Session-ID */ 280*a93a1f58Sgm209912 begin = ++current; 281*a93a1f58Sgm209912 if (commp_find_token(&begin, ¤t, end, COMMP_SP, B_FALSE) != 0) 282*a93a1f58Sgm209912 goto err_ret; 283*a93a1f58Sgm209912 if (commp_strtoull(begin, current, &new_origin->o_id) != 0) 284*a93a1f58Sgm209912 goto err_ret; 285*a93a1f58Sgm209912 /* Get Version */ 286*a93a1f58Sgm209912 begin = ++current; 287*a93a1f58Sgm209912 if (commp_find_token(&begin, ¤t, end, COMMP_SP, B_FALSE) != 0) 288*a93a1f58Sgm209912 goto err_ret; 289*a93a1f58Sgm209912 if (commp_strtoull(begin, current, &new_origin->o_version) != 0) 290*a93a1f58Sgm209912 goto err_ret; 291*a93a1f58Sgm209912 /* Get nettype */ 292*a93a1f58Sgm209912 begin = ++current; 293*a93a1f58Sgm209912 if (commp_find_token(&begin, ¤t, end, COMMP_SP, B_FALSE) != 0) { 294*a93a1f58Sgm209912 goto err_ret; 295*a93a1f58Sgm209912 } else { 296*a93a1f58Sgm209912 COMMP_COPY_STR(new_origin->o_nettype, begin, current - begin); 297*a93a1f58Sgm209912 if (new_origin->o_nettype == NULL) { 298*a93a1f58Sgm209912 sdp_free_origin(new_origin); 299*a93a1f58Sgm209912 *p_error |= SDP_MEMORY_ERROR; 300*a93a1f58Sgm209912 return; 301*a93a1f58Sgm209912 } 302*a93a1f58Sgm209912 } 303*a93a1f58Sgm209912 /* Get addrtype */ 304*a93a1f58Sgm209912 begin = ++current; 305*a93a1f58Sgm209912 if (commp_find_token(&begin, ¤t, end, COMMP_SP, B_FALSE) != 0) { 306*a93a1f58Sgm209912 goto err_ret; 307*a93a1f58Sgm209912 } else { 308*a93a1f58Sgm209912 COMMP_COPY_STR(new_origin->o_addrtype, begin, current - begin); 309*a93a1f58Sgm209912 if (new_origin->o_addrtype == NULL) { 310*a93a1f58Sgm209912 sdp_free_origin(new_origin); 311*a93a1f58Sgm209912 *p_error |= SDP_MEMORY_ERROR; 312*a93a1f58Sgm209912 return; 313*a93a1f58Sgm209912 } 314*a93a1f58Sgm209912 } 315*a93a1f58Sgm209912 /* Get address. Its the last sub-field */ 316*a93a1f58Sgm209912 begin = ++current; 317*a93a1f58Sgm209912 if (commp_find_token(&begin, ¤t, end, COMMP_SP, B_TRUE) != 0) 318*a93a1f58Sgm209912 goto err_ret; 319*a93a1f58Sgm209912 COMMP_COPY_STR(new_origin->o_address, begin, current - begin); 320*a93a1f58Sgm209912 if (new_origin->o_address == NULL) { 321*a93a1f58Sgm209912 sdp_free_origin(new_origin); 322*a93a1f58Sgm209912 *p_error |= SDP_MEMORY_ERROR; 323*a93a1f58Sgm209912 return; 324*a93a1f58Sgm209912 } 325*a93a1f58Sgm209912 *origin = new_origin; 326*a93a1f58Sgm209912 return; 327*a93a1f58Sgm209912 err_ret: 328*a93a1f58Sgm209912 *p_error |= SDP_ORIGIN_ERROR; 329*a93a1f58Sgm209912 sdp_free_origin(new_origin); 330*a93a1f58Sgm209912 } 331*a93a1f58Sgm209912 332*a93a1f58Sgm209912 /* 333*a93a1f58Sgm209912 * time-fields (t=) 334*a93a1f58Sgm209912 * 1*( %x74 "=" start-time SP stop-time CRLF) 335*a93a1f58Sgm209912 * start-time = time / "0" 336*a93a1f58Sgm209912 * stop-time = time / "0" 337*a93a1f58Sgm209912 * time = POS-DIGIT 9*DIGIT 338*a93a1f58Sgm209912 * POS-DIGIT = %x31-39 ; 1 - 9 339*a93a1f58Sgm209912 */ 340*a93a1f58Sgm209912 static sdp_time_t * 341*a93a1f58Sgm209912 sdp_parse_time(sdp_time_t **time, const char *begin, const char *end, 342*a93a1f58Sgm209912 uint_t *p_error) 343*a93a1f58Sgm209912 { 344*a93a1f58Sgm209912 const char *current; 345*a93a1f58Sgm209912 sdp_time_t *new_time; 346*a93a1f58Sgm209912 sdp_time_t *tmp; 347*a93a1f58Sgm209912 348*a93a1f58Sgm209912 if (*begin++ != COMMP_EQUALS) { 349*a93a1f58Sgm209912 *p_error |= SDP_TIME_ERROR; 350*a93a1f58Sgm209912 return (NULL); 351*a93a1f58Sgm209912 } 352*a93a1f58Sgm209912 new_time = calloc(1, sizeof (sdp_time_t)); 353*a93a1f58Sgm209912 if (new_time == NULL) { 354*a93a1f58Sgm209912 *p_error |= SDP_MEMORY_ERROR; 355*a93a1f58Sgm209912 return (NULL); 356*a93a1f58Sgm209912 } 357*a93a1f58Sgm209912 /* Get start-time */ 358*a93a1f58Sgm209912 current = begin; 359*a93a1f58Sgm209912 if (commp_find_token(&begin, ¤t, end, COMMP_SP, B_FALSE) != 0) 360*a93a1f58Sgm209912 goto err_ret; 361*a93a1f58Sgm209912 if (commp_strtoull(begin, current, &new_time->t_start) != 0) 362*a93a1f58Sgm209912 goto err_ret; 363*a93a1f58Sgm209912 /* Get stop-time */ 364*a93a1f58Sgm209912 begin = ++current; 365*a93a1f58Sgm209912 if (commp_find_token(&begin, ¤t, end, COMMP_SP, B_TRUE) != 0) 366*a93a1f58Sgm209912 goto err_ret; 367*a93a1f58Sgm209912 if (commp_strtoull(begin, current, &new_time->t_stop) != 0) 368*a93a1f58Sgm209912 goto err_ret; 369*a93a1f58Sgm209912 /* Now assign time to session structure */ 370*a93a1f58Sgm209912 if (*time == NULL) { 371*a93a1f58Sgm209912 *time = new_time; 372*a93a1f58Sgm209912 } else { 373*a93a1f58Sgm209912 tmp = *time; 374*a93a1f58Sgm209912 while (tmp->t_next != NULL) 375*a93a1f58Sgm209912 tmp = tmp->t_next; 376*a93a1f58Sgm209912 tmp->t_next = new_time; 377*a93a1f58Sgm209912 } 378*a93a1f58Sgm209912 return (new_time); 379*a93a1f58Sgm209912 err_ret: 380*a93a1f58Sgm209912 *p_error |= SDP_TIME_ERROR; 381*a93a1f58Sgm209912 sdp_free_time(new_time); 382*a93a1f58Sgm209912 return (NULL); 383*a93a1f58Sgm209912 } 384*a93a1f58Sgm209912 385*a93a1f58Sgm209912 /* 386*a93a1f58Sgm209912 * connection-field (c=) 387*a93a1f58Sgm209912 * [%x63 "=" nettype SP addrtype SP connection-address CRLF] 388*a93a1f58Sgm209912 * nettype = token 389*a93a1f58Sgm209912 * addrtype = token 390*a93a1f58Sgm209912 * connection-address = multicast-address / unicast-address 391*a93a1f58Sgm209912 * here, connection-address is parsed as a string. 392*a93a1f58Sgm209912 */ 393*a93a1f58Sgm209912 static void 394*a93a1f58Sgm209912 sdp_parse_connection(sdp_conn_t **conn, const char *begin, const char *end, 395*a93a1f58Sgm209912 uint_t *p_error) 396*a93a1f58Sgm209912 { 397*a93a1f58Sgm209912 const char *current; 398*a93a1f58Sgm209912 const char *t_begin; 399*a93a1f58Sgm209912 const char *t_current; 400*a93a1f58Sgm209912 sdp_conn_t *new_conn; 401*a93a1f58Sgm209912 sdp_conn_t *tmp; 402*a93a1f58Sgm209912 boolean_t is_IP4 = B_FALSE; 403*a93a1f58Sgm209912 boolean_t is_IP6 = B_FALSE; 404*a93a1f58Sgm209912 405*a93a1f58Sgm209912 if (*begin++ != COMMP_EQUALS) { 406*a93a1f58Sgm209912 *p_error |= SDP_CONNECTION_ERROR; 407*a93a1f58Sgm209912 return; 408*a93a1f58Sgm209912 } 409*a93a1f58Sgm209912 new_conn = calloc(1, sizeof (sdp_conn_t)); 410*a93a1f58Sgm209912 if (new_conn == NULL) { 411*a93a1f58Sgm209912 *p_error |= SDP_MEMORY_ERROR; 412*a93a1f58Sgm209912 return; 413*a93a1f58Sgm209912 } 414*a93a1f58Sgm209912 /* Get NetworkType */ 415*a93a1f58Sgm209912 current = begin; 416*a93a1f58Sgm209912 if (commp_find_token(&begin, ¤t, end, COMMP_SP, B_FALSE) != 0) { 417*a93a1f58Sgm209912 goto err_ret; 418*a93a1f58Sgm209912 } else { 419*a93a1f58Sgm209912 COMMP_COPY_STR(new_conn->c_nettype, begin, current - begin); 420*a93a1f58Sgm209912 if (new_conn->c_nettype == NULL) { 421*a93a1f58Sgm209912 sdp_free_connection(new_conn); 422*a93a1f58Sgm209912 *p_error |= SDP_MEMORY_ERROR; 423*a93a1f58Sgm209912 return; 424*a93a1f58Sgm209912 } 425*a93a1f58Sgm209912 } 426*a93a1f58Sgm209912 /* Get AddressType */ 427*a93a1f58Sgm209912 begin = ++current; 428*a93a1f58Sgm209912 if (commp_find_token(&begin, ¤t, end, COMMP_SP, B_FALSE) != 0) { 429*a93a1f58Sgm209912 goto err_ret; 430*a93a1f58Sgm209912 } else { 431*a93a1f58Sgm209912 COMMP_COPY_STR(new_conn->c_addrtype, begin, current - begin); 432*a93a1f58Sgm209912 if (new_conn->c_addrtype == NULL) { 433*a93a1f58Sgm209912 sdp_free_connection(new_conn); 434*a93a1f58Sgm209912 *p_error |= SDP_MEMORY_ERROR; 435*a93a1f58Sgm209912 return; 436*a93a1f58Sgm209912 } 437*a93a1f58Sgm209912 } 438*a93a1f58Sgm209912 if ((strlen(COMMP_ADDRTYPE_IP4) == strlen(new_conn->c_addrtype)) && 439*a93a1f58Sgm209912 (strncasecmp(new_conn->c_addrtype, COMMP_ADDRTYPE_IP4, 440*a93a1f58Sgm209912 strlen(COMMP_ADDRTYPE_IP4)) == 0)) { 441*a93a1f58Sgm209912 is_IP4 = B_TRUE; 442*a93a1f58Sgm209912 } else if ((strlen(COMMP_ADDRTYPE_IP6) == strlen(new_conn-> 443*a93a1f58Sgm209912 c_addrtype)) && (strncasecmp(new_conn->c_addrtype, 444*a93a1f58Sgm209912 COMMP_ADDRTYPE_IP6, strlen(COMMP_ADDRTYPE_IP6)) == 0)) { 445*a93a1f58Sgm209912 is_IP6 = B_TRUE; 446*a93a1f58Sgm209912 } 447*a93a1f58Sgm209912 /* Get Address. Parsing depends if its IP4,IP6 or something else */ 448*a93a1f58Sgm209912 begin = ++current; 449*a93a1f58Sgm209912 if (!is_IP4 && !is_IP6) { 450*a93a1f58Sgm209912 if (commp_find_token(&begin, ¤t, end, COMMP_SP, 451*a93a1f58Sgm209912 B_TRUE) != 0) { 452*a93a1f58Sgm209912 goto err_ret; 453*a93a1f58Sgm209912 } 454*a93a1f58Sgm209912 } else { 455*a93a1f58Sgm209912 if (commp_find_token(&begin, ¤t, end, COMMP_SLASH, 456*a93a1f58Sgm209912 B_FALSE) != 0) { 457*a93a1f58Sgm209912 goto err_ret; 458*a93a1f58Sgm209912 } 459*a93a1f58Sgm209912 if (current != end) { 460*a93a1f58Sgm209912 /* SLASH is present. Needs further parsing */ 461*a93a1f58Sgm209912 t_current = current; 462*a93a1f58Sgm209912 t_begin = ++t_current; 463*a93a1f58Sgm209912 if (commp_find_token(&t_begin, &t_current, end, 464*a93a1f58Sgm209912 COMMP_SLASH, B_FALSE) != 0) { 465*a93a1f58Sgm209912 goto err_ret; 466*a93a1f58Sgm209912 } 467*a93a1f58Sgm209912 if (t_current != end) { 468*a93a1f58Sgm209912 /* 469*a93a1f58Sgm209912 * Another SLASH present. If is_IP4 true then 470*a93a1f58Sgm209912 * this is Address count. If is_IP6 true then 471*a93a1f58Sgm209912 * incorrect field as per RFC. 472*a93a1f58Sgm209912 */ 473*a93a1f58Sgm209912 if (is_IP6) { 474*a93a1f58Sgm209912 goto err_ret; 475*a93a1f58Sgm209912 } else { 476*a93a1f58Sgm209912 if (commp_atoi((t_current + 1), end, 477*a93a1f58Sgm209912 &new_conn->c_addrcount) != 0) { 478*a93a1f58Sgm209912 goto err_ret; 479*a93a1f58Sgm209912 } 480*a93a1f58Sgm209912 } 481*a93a1f58Sgm209912 } 482*a93a1f58Sgm209912 if (is_IP6) { 483*a93a1f58Sgm209912 if (commp_atoi((current + 1), t_current, 484*a93a1f58Sgm209912 &new_conn->c_addrcount) != 0) { 485*a93a1f58Sgm209912 goto err_ret; 486*a93a1f58Sgm209912 } 487*a93a1f58Sgm209912 } else { 488*a93a1f58Sgm209912 if (commp_strtoub((current + 1), t_current, 489*a93a1f58Sgm209912 &new_conn->c_ttl) != 0) { 490*a93a1f58Sgm209912 goto err_ret; 491*a93a1f58Sgm209912 } 492*a93a1f58Sgm209912 if (new_conn->c_addrcount == 0) 493*a93a1f58Sgm209912 new_conn->c_addrcount = 1; 494*a93a1f58Sgm209912 } 495*a93a1f58Sgm209912 } 496*a93a1f58Sgm209912 } 497*a93a1f58Sgm209912 COMMP_COPY_STR(new_conn->c_address, begin, current - begin); 498*a93a1f58Sgm209912 if (new_conn->c_address == NULL) { 499*a93a1f58Sgm209912 sdp_free_connection(new_conn); 500*a93a1f58Sgm209912 *p_error |= SDP_MEMORY_ERROR; 501*a93a1f58Sgm209912 return; 502*a93a1f58Sgm209912 } 503*a93a1f58Sgm209912 if (*conn == NULL) { 504*a93a1f58Sgm209912 *conn = new_conn; 505*a93a1f58Sgm209912 } else { 506*a93a1f58Sgm209912 tmp = *conn; 507*a93a1f58Sgm209912 while (tmp->c_next != NULL) 508*a93a1f58Sgm209912 tmp = tmp->c_next; 509*a93a1f58Sgm209912 tmp->c_next = new_conn; 510*a93a1f58Sgm209912 } 511*a93a1f58Sgm209912 return; 512*a93a1f58Sgm209912 err_ret: 513*a93a1f58Sgm209912 *p_error |= SDP_CONNECTION_ERROR; 514*a93a1f58Sgm209912 sdp_free_connection(new_conn); 515*a93a1f58Sgm209912 } 516*a93a1f58Sgm209912 517*a93a1f58Sgm209912 /* 518*a93a1f58Sgm209912 * bandwidth-fields (b=) 519*a93a1f58Sgm209912 * *(%x62 "=" bwtype ":" bandwidth CRLF) 520*a93a1f58Sgm209912 * bwtype = token 521*a93a1f58Sgm209912 * bandwidth = 1*DIGIT 522*a93a1f58Sgm209912 */ 523*a93a1f58Sgm209912 static void 524*a93a1f58Sgm209912 sdp_parse_bandwidth(sdp_bandwidth_t **bw, const char *begin, const char *end, 525*a93a1f58Sgm209912 uint_t *p_error) 526*a93a1f58Sgm209912 { 527*a93a1f58Sgm209912 const char *current; 528*a93a1f58Sgm209912 sdp_bandwidth_t *new_bw = NULL; 529*a93a1f58Sgm209912 sdp_bandwidth_t *tmp = NULL; 530*a93a1f58Sgm209912 531*a93a1f58Sgm209912 if (*begin++ != COMMP_EQUALS) { 532*a93a1f58Sgm209912 *p_error |= SDP_BANDWIDTH_ERROR; 533*a93a1f58Sgm209912 return; 534*a93a1f58Sgm209912 } 535*a93a1f58Sgm209912 new_bw = calloc(1, sizeof (sdp_bandwidth_t)); 536*a93a1f58Sgm209912 if (new_bw == NULL) { 537*a93a1f58Sgm209912 *p_error |= SDP_MEMORY_ERROR; 538*a93a1f58Sgm209912 return; 539*a93a1f58Sgm209912 } 540*a93a1f58Sgm209912 current = begin; 541*a93a1f58Sgm209912 if (commp_find_token(&begin, ¤t, end, COMMP_COLON, 542*a93a1f58Sgm209912 B_FALSE) != 0) { 543*a93a1f58Sgm209912 goto err_ret; 544*a93a1f58Sgm209912 } else { 545*a93a1f58Sgm209912 COMMP_COPY_STR(new_bw->b_type, begin, current - begin); 546*a93a1f58Sgm209912 if (new_bw->b_type == NULL) { 547*a93a1f58Sgm209912 sdp_free_bandwidth(new_bw); 548*a93a1f58Sgm209912 *p_error |= SDP_MEMORY_ERROR; 549*a93a1f58Sgm209912 return; 550*a93a1f58Sgm209912 } 551*a93a1f58Sgm209912 } 552*a93a1f58Sgm209912 if (current == end) 553*a93a1f58Sgm209912 goto err_ret; 554*a93a1f58Sgm209912 begin = ++current; 555*a93a1f58Sgm209912 if (commp_find_token(&begin, ¤t, end, COMMP_SP, B_TRUE) != 0) 556*a93a1f58Sgm209912 goto err_ret; 557*a93a1f58Sgm209912 if (commp_strtoull(begin, current, &new_bw->b_value) != 0) 558*a93a1f58Sgm209912 goto err_ret; 559*a93a1f58Sgm209912 if (*bw == NULL) { 560*a93a1f58Sgm209912 *bw = new_bw; 561*a93a1f58Sgm209912 } else { 562*a93a1f58Sgm209912 tmp = *bw; 563*a93a1f58Sgm209912 while (tmp->b_next != NULL) 564*a93a1f58Sgm209912 tmp = tmp->b_next; 565*a93a1f58Sgm209912 tmp->b_next = new_bw; 566*a93a1f58Sgm209912 } 567*a93a1f58Sgm209912 return; 568*a93a1f58Sgm209912 err_ret: 569*a93a1f58Sgm209912 *p_error |= SDP_BANDWIDTH_ERROR; 570*a93a1f58Sgm209912 sdp_free_bandwidth(new_bw); 571*a93a1f58Sgm209912 } 572*a93a1f58Sgm209912 573*a93a1f58Sgm209912 /* 574*a93a1f58Sgm209912 * repeat-fields (r=) 575*a93a1f58Sgm209912 * Not stand-alone. One or more repeat field appear after time field. 576*a93a1f58Sgm209912 * %x72 "=" repeat-interval SP typed-time 1*(SP typed-time) 577*a93a1f58Sgm209912 * repeat-interval = POS-DIGIT *DIGIT [fixed-len-time-unit] 578*a93a1f58Sgm209912 * typed-time = 1*DIGIT [fixed-len-time-unit] 579*a93a1f58Sgm209912 * fixed-len-time-unit = %x64 / %x68 / %x6d / %x73 580*a93a1f58Sgm209912 */ 581*a93a1f58Sgm209912 static void 582*a93a1f58Sgm209912 sdp_parse_repeat(sdp_time_t *time, const char *begin, const char *end, 583*a93a1f58Sgm209912 uint_t *p_error) 584*a93a1f58Sgm209912 { 585*a93a1f58Sgm209912 const char *current; 586*a93a1f58Sgm209912 sdp_repeat_t *repeat; 587*a93a1f58Sgm209912 sdp_repeat_t *new_repeat; 588*a93a1f58Sgm209912 int ret; 589*a93a1f58Sgm209912 590*a93a1f58Sgm209912 if (*begin++ != COMMP_EQUALS) { 591*a93a1f58Sgm209912 *p_error |= SDP_REPEAT_TIME_ERROR; 592*a93a1f58Sgm209912 return; 593*a93a1f58Sgm209912 } 594*a93a1f58Sgm209912 /* 595*a93a1f58Sgm209912 * A time field should be present before this field can occur, if 596*a93a1f58Sgm209912 * time is NULL then repeat field has occured before time field and 597*a93a1f58Sgm209912 * hence fields are out of order. 598*a93a1f58Sgm209912 */ 599*a93a1f58Sgm209912 if (time == NULL) 600*a93a1f58Sgm209912 return; 601*a93a1f58Sgm209912 /* 602*a93a1f58Sgm209912 * Get the latest time field and associate this repeat field 603*a93a1f58Sgm209912 * with it. 604*a93a1f58Sgm209912 */ 605*a93a1f58Sgm209912 while (time->t_next != NULL) 606*a93a1f58Sgm209912 time = time->t_next; 607*a93a1f58Sgm209912 new_repeat = calloc(1, sizeof (sdp_repeat_t)); 608*a93a1f58Sgm209912 if (new_repeat == NULL) { 609*a93a1f58Sgm209912 *p_error |= SDP_MEMORY_ERROR; 610*a93a1f58Sgm209912 return; 611*a93a1f58Sgm209912 } 612*a93a1f58Sgm209912 /* 613*a93a1f58Sgm209912 * for a given time field, there could be several repeat fields 614*a93a1f58Sgm209912 * add the new repeat field at the end of it. 615*a93a1f58Sgm209912 */ 616*a93a1f58Sgm209912 repeat = time->t_repeat; 617*a93a1f58Sgm209912 if (repeat == NULL) { 618*a93a1f58Sgm209912 time->t_repeat = new_repeat; 619*a93a1f58Sgm209912 } else { 620*a93a1f58Sgm209912 while (repeat->r_next != NULL) 621*a93a1f58Sgm209912 repeat = repeat->r_next; 622*a93a1f58Sgm209912 repeat->r_next = new_repeat; 623*a93a1f58Sgm209912 } 624*a93a1f58Sgm209912 /* 625*a93a1f58Sgm209912 * Populate the elements of sdp_repeat. 626*a93a1f58Sgm209912 * Get time-interval 627*a93a1f58Sgm209912 */ 628*a93a1f58Sgm209912 current = begin; 629*a93a1f58Sgm209912 if (commp_find_token(&begin, ¤t, end, COMMP_SP, B_FALSE) != 0) 630*a93a1f58Sgm209912 goto err_ret; 631*a93a1f58Sgm209912 if (commp_time_to_secs(begin, current, &new_repeat->r_interval) != 0) 632*a93a1f58Sgm209912 goto err_ret; 633*a93a1f58Sgm209912 /* Get duration. It could be the last sub-field */ 634*a93a1f58Sgm209912 begin = ++current; 635*a93a1f58Sgm209912 if (commp_find_token(&begin, ¤t, end, COMMP_SP, B_FALSE) != 0) 636*a93a1f58Sgm209912 goto err_ret; 637*a93a1f58Sgm209912 if (commp_time_to_secs(begin, current, &new_repeat->r_duration) != 0) 638*a93a1f58Sgm209912 goto err_ret; 639*a93a1f58Sgm209912 ++current; 640*a93a1f58Sgm209912 /* Get offsets into sdp_list */ 641*a93a1f58Sgm209912 if (current >= end) 642*a93a1f58Sgm209912 goto err_ret; 643*a93a1f58Sgm209912 while (current < end) { 644*a93a1f58Sgm209912 begin = current; 645*a93a1f58Sgm209912 if (commp_find_token(&begin, ¤t, end, COMMP_SP, 646*a93a1f58Sgm209912 B_FALSE) != 0) { 647*a93a1f58Sgm209912 goto err_ret; 648*a93a1f58Sgm209912 } 649*a93a1f58Sgm209912 if ((ret = add_value_to_list(&new_repeat->r_offset, begin, 650*a93a1f58Sgm209912 current - begin, B_FALSE)) != 0) { 651*a93a1f58Sgm209912 if (ret == ENOMEM) { 652*a93a1f58Sgm209912 *p_error |= SDP_MEMORY_ERROR; 653*a93a1f58Sgm209912 return; 654*a93a1f58Sgm209912 } else { 655*a93a1f58Sgm209912 goto err_ret; 656*a93a1f58Sgm209912 } 657*a93a1f58Sgm209912 } 658*a93a1f58Sgm209912 ++current; 659*a93a1f58Sgm209912 } 660*a93a1f58Sgm209912 /* check for trailing white space character. */ 661*a93a1f58Sgm209912 if (isspace(*(end - 1))) 662*a93a1f58Sgm209912 goto err_ret; 663*a93a1f58Sgm209912 return; 664*a93a1f58Sgm209912 err_ret: 665*a93a1f58Sgm209912 *p_error |= SDP_REPEAT_TIME_ERROR; 666*a93a1f58Sgm209912 if (repeat != NULL) 667*a93a1f58Sgm209912 repeat->r_next = NULL; 668*a93a1f58Sgm209912 else 669*a93a1f58Sgm209912 time->t_repeat = NULL; 670*a93a1f58Sgm209912 sdp_free_repeat(new_repeat); 671*a93a1f58Sgm209912 } 672*a93a1f58Sgm209912 673*a93a1f58Sgm209912 /* 674*a93a1f58Sgm209912 * zone-adjustments (z=) 675*a93a1f58Sgm209912 * %x7a "=" time SP ["-"] typed-time *(SP time SP ["-"] typed-time) 676*a93a1f58Sgm209912 */ 677*a93a1f58Sgm209912 static void 678*a93a1f58Sgm209912 sdp_parse_zone(sdp_zone_t **zone, const char *begin, const char *end, 679*a93a1f58Sgm209912 uint_t *p_error) 680*a93a1f58Sgm209912 { 681*a93a1f58Sgm209912 const char *current; 682*a93a1f58Sgm209912 sdp_zone_t *new_zone = NULL; 683*a93a1f58Sgm209912 sdp_zone_t *tmp = NULL; 684*a93a1f58Sgm209912 685*a93a1f58Sgm209912 if (*begin++ != COMMP_EQUALS) { 686*a93a1f58Sgm209912 *p_error |= SDP_ZONE_ERROR; 687*a93a1f58Sgm209912 return; 688*a93a1f58Sgm209912 } 689*a93a1f58Sgm209912 /* There can be atmost one zone field. */ 690*a93a1f58Sgm209912 if (*zone != NULL) 691*a93a1f58Sgm209912 return; 692*a93a1f58Sgm209912 /* Get time and offset */ 693*a93a1f58Sgm209912 current = begin; 694*a93a1f58Sgm209912 while (current < end) { 695*a93a1f58Sgm209912 new_zone = calloc(1, sizeof (sdp_zone_t)); 696*a93a1f58Sgm209912 if (new_zone == NULL) { 697*a93a1f58Sgm209912 *p_error |= SDP_MEMORY_ERROR; 698*a93a1f58Sgm209912 return; 699*a93a1f58Sgm209912 } 700*a93a1f58Sgm209912 if (*zone == NULL) { 701*a93a1f58Sgm209912 *zone = new_zone; 702*a93a1f58Sgm209912 tmp = *zone; 703*a93a1f58Sgm209912 } else { 704*a93a1f58Sgm209912 tmp->z_next = new_zone; 705*a93a1f58Sgm209912 tmp = new_zone; 706*a93a1f58Sgm209912 } 707*a93a1f58Sgm209912 begin = current; 708*a93a1f58Sgm209912 if (commp_find_token(&begin, ¤t, end, COMMP_SP, 709*a93a1f58Sgm209912 B_FALSE) != 0) { 710*a93a1f58Sgm209912 goto err_ret; 711*a93a1f58Sgm209912 } 712*a93a1f58Sgm209912 if (commp_strtoull(begin, current, &new_zone->z_time) != 0) 713*a93a1f58Sgm209912 goto err_ret; 714*a93a1f58Sgm209912 begin = ++current; 715*a93a1f58Sgm209912 if (commp_find_token(&begin, ¤t, end, COMMP_SP, 716*a93a1f58Sgm209912 B_FALSE) != 0) { 717*a93a1f58Sgm209912 goto err_ret; 718*a93a1f58Sgm209912 } else { 719*a93a1f58Sgm209912 COMMP_COPY_STR(new_zone->z_offset, begin, current - 720*a93a1f58Sgm209912 begin); 721*a93a1f58Sgm209912 if (new_zone->z_offset == NULL) { 722*a93a1f58Sgm209912 *p_error |= SDP_MEMORY_ERROR; 723*a93a1f58Sgm209912 return; 724*a93a1f58Sgm209912 } 725*a93a1f58Sgm209912 726*a93a1f58Sgm209912 } 727*a93a1f58Sgm209912 ++current; 728*a93a1f58Sgm209912 } 729*a93a1f58Sgm209912 if (isspace(*(end - 1))) 730*a93a1f58Sgm209912 goto err_ret; 731*a93a1f58Sgm209912 return; 732*a93a1f58Sgm209912 err_ret: 733*a93a1f58Sgm209912 *p_error |= SDP_ZONE_ERROR; 734*a93a1f58Sgm209912 sdp_free_zone(*zone); 735*a93a1f58Sgm209912 *zone = NULL; 736*a93a1f58Sgm209912 } 737*a93a1f58Sgm209912 738*a93a1f58Sgm209912 /* 739*a93a1f58Sgm209912 * key-field (k=) 740*a93a1f58Sgm209912 * [%x6b "=" key-type CRLF] 741*a93a1f58Sgm209912 * key-type = %x70 %x72 %x6f %x6d %x70 %x74 / ; "prompt" 742*a93a1f58Sgm209912 * %x63 %x6c %x65 %x61 %x72 ":" text / ; "clear:" 743*a93a1f58Sgm209912 * %x62 %x61 %x73 %x65 "64:" base64 / ; "base64:" 744*a93a1f58Sgm209912 * %x75 %x72 %x69 ":" uri ; "uri:" 745*a93a1f58Sgm209912 */ 746*a93a1f58Sgm209912 static void 747*a93a1f58Sgm209912 sdp_parse_key(sdp_key_t **key, const char *begin, const char *end, 748*a93a1f58Sgm209912 uint_t *p_error) 749*a93a1f58Sgm209912 { 750*a93a1f58Sgm209912 const char *current; 751*a93a1f58Sgm209912 sdp_key_t *new_key; 752*a93a1f58Sgm209912 753*a93a1f58Sgm209912 if (*begin++ != COMMP_EQUALS) { 754*a93a1f58Sgm209912 *p_error |= SDP_KEY_ERROR; 755*a93a1f58Sgm209912 return; 756*a93a1f58Sgm209912 } 757*a93a1f58Sgm209912 /* There can be only one key field */ 758*a93a1f58Sgm209912 if (*key != NULL) 759*a93a1f58Sgm209912 return; 760*a93a1f58Sgm209912 new_key = calloc(1, sizeof (sdp_key_t)); 761*a93a1f58Sgm209912 if (new_key == NULL) { 762*a93a1f58Sgm209912 *p_error |= SDP_MEMORY_ERROR; 763*a93a1f58Sgm209912 return; 764*a93a1f58Sgm209912 } 765*a93a1f58Sgm209912 /* Get Method name */ 766*a93a1f58Sgm209912 current = begin; 767*a93a1f58Sgm209912 if (commp_find_token(&begin, ¤t, end, COMMP_COLON, 768*a93a1f58Sgm209912 B_FALSE) != 0) { 769*a93a1f58Sgm209912 goto err_ret; 770*a93a1f58Sgm209912 } else { 771*a93a1f58Sgm209912 COMMP_COPY_STR(new_key->k_method, begin, current - begin); 772*a93a1f58Sgm209912 if (new_key->k_method == NULL) { 773*a93a1f58Sgm209912 sdp_free_key(new_key); 774*a93a1f58Sgm209912 *p_error |= SDP_MEMORY_ERROR; 775*a93a1f58Sgm209912 return; 776*a93a1f58Sgm209912 } 777*a93a1f58Sgm209912 } 778*a93a1f58Sgm209912 /* Get key, if exists. */ 779*a93a1f58Sgm209912 if (*current == COMMP_COLON) { 780*a93a1f58Sgm209912 ++current; 781*a93a1f58Sgm209912 if (current == end) 782*a93a1f58Sgm209912 goto err_ret; 783*a93a1f58Sgm209912 COMMP_COPY_STR(new_key->k_enckey, current, end - current); 784*a93a1f58Sgm209912 if (new_key->k_enckey == NULL) { 785*a93a1f58Sgm209912 sdp_free_key(new_key); 786*a93a1f58Sgm209912 *p_error |= SDP_MEMORY_ERROR; 787*a93a1f58Sgm209912 return; 788*a93a1f58Sgm209912 } 789*a93a1f58Sgm209912 } 790*a93a1f58Sgm209912 *key = new_key; 791*a93a1f58Sgm209912 return; 792*a93a1f58Sgm209912 err_ret: 793*a93a1f58Sgm209912 *p_error |= SDP_KEY_ERROR; 794*a93a1f58Sgm209912 sdp_free_key(new_key); 795*a93a1f58Sgm209912 } 796*a93a1f58Sgm209912 797*a93a1f58Sgm209912 /* 798*a93a1f58Sgm209912 * attribute-fields (a=) 799*a93a1f58Sgm209912 * *(%x61 "=" attribute CRLF) 800*a93a1f58Sgm209912 * attribute = (att-field ":" att-value) / att-field 801*a93a1f58Sgm209912 * att-field = token 802*a93a1f58Sgm209912 * att-value = byte-string 803*a93a1f58Sgm209912 */ 804*a93a1f58Sgm209912 static void 805*a93a1f58Sgm209912 sdp_parse_attribute(sdp_attr_t **attr, const char *begin, const char *end, 806*a93a1f58Sgm209912 uint_t *p_error) 807*a93a1f58Sgm209912 { 808*a93a1f58Sgm209912 const char *current; 809*a93a1f58Sgm209912 sdp_attr_t *new_attr; 810*a93a1f58Sgm209912 sdp_attr_t *tmp; 811*a93a1f58Sgm209912 812*a93a1f58Sgm209912 if (*begin++ != COMMP_EQUALS) { 813*a93a1f58Sgm209912 *p_error |= SDP_ATTRIBUTE_ERROR; 814*a93a1f58Sgm209912 return; 815*a93a1f58Sgm209912 } 816*a93a1f58Sgm209912 new_attr = calloc(1, sizeof (sdp_attr_t)); 817*a93a1f58Sgm209912 if (new_attr == NULL) { 818*a93a1f58Sgm209912 *p_error |= SDP_MEMORY_ERROR; 819*a93a1f58Sgm209912 return; 820*a93a1f58Sgm209912 } 821*a93a1f58Sgm209912 /* Get Attribute Name */ 822*a93a1f58Sgm209912 current = begin; 823*a93a1f58Sgm209912 if (commp_find_token(&begin, ¤t, end, COMMP_COLON, 824*a93a1f58Sgm209912 B_FALSE) != 0) { 825*a93a1f58Sgm209912 goto err_ret; 826*a93a1f58Sgm209912 } else { 827*a93a1f58Sgm209912 COMMP_COPY_STR(new_attr->a_name, begin, current - begin); 828*a93a1f58Sgm209912 if (new_attr->a_name == NULL) { 829*a93a1f58Sgm209912 sdp_free_attribute(new_attr); 830*a93a1f58Sgm209912 *p_error |= SDP_MEMORY_ERROR; 831*a93a1f58Sgm209912 return; 832*a93a1f58Sgm209912 } 833*a93a1f58Sgm209912 } 834*a93a1f58Sgm209912 /* Get Attribute Value */ 835*a93a1f58Sgm209912 if (*current == COMMP_COLON) { 836*a93a1f58Sgm209912 ++current; 837*a93a1f58Sgm209912 if (current == end) 838*a93a1f58Sgm209912 goto err_ret; 839*a93a1f58Sgm209912 COMMP_COPY_STR(new_attr->a_value, current, end - current); 840*a93a1f58Sgm209912 if (new_attr->a_value == NULL) { 841*a93a1f58Sgm209912 sdp_free_attribute(new_attr); 842*a93a1f58Sgm209912 *p_error |= SDP_MEMORY_ERROR; 843*a93a1f58Sgm209912 return; 844*a93a1f58Sgm209912 } 845*a93a1f58Sgm209912 } 846*a93a1f58Sgm209912 if (*attr == NULL) { 847*a93a1f58Sgm209912 *attr = new_attr; 848*a93a1f58Sgm209912 } else { 849*a93a1f58Sgm209912 tmp = *attr; 850*a93a1f58Sgm209912 while (tmp->a_next != NULL) 851*a93a1f58Sgm209912 tmp = tmp->a_next; 852*a93a1f58Sgm209912 tmp->a_next = new_attr; 853*a93a1f58Sgm209912 } 854*a93a1f58Sgm209912 return; 855*a93a1f58Sgm209912 err_ret: 856*a93a1f58Sgm209912 *p_error |= SDP_ATTRIBUTE_ERROR; 857*a93a1f58Sgm209912 sdp_free_attribute(new_attr); 858*a93a1f58Sgm209912 } 859*a93a1f58Sgm209912 860*a93a1f58Sgm209912 /* 861*a93a1f58Sgm209912 * media-field (m=) 862*a93a1f58Sgm209912 * %x6d "=" media SP port ["/" integer] SP proto 1*(SP fmt) CRLF 863*a93a1f58Sgm209912 */ 864*a93a1f58Sgm209912 static sdp_media_t * 865*a93a1f58Sgm209912 sdp_parse_media(sdp_session_t *session, const char *begin, const char *end, 866*a93a1f58Sgm209912 uint_t *p_error) 867*a93a1f58Sgm209912 { 868*a93a1f58Sgm209912 const char *current; 869*a93a1f58Sgm209912 const char *fake_end; 870*a93a1f58Sgm209912 sdp_media_t *new_media; 871*a93a1f58Sgm209912 sdp_media_t *tmp; 872*a93a1f58Sgm209912 873*a93a1f58Sgm209912 if (*begin++ != COMMP_EQUALS) { 874*a93a1f58Sgm209912 *p_error |= SDP_MEDIA_ERROR; 875*a93a1f58Sgm209912 return (NULL); 876*a93a1f58Sgm209912 } 877*a93a1f58Sgm209912 878*a93a1f58Sgm209912 new_media = calloc(1, sizeof (sdp_media_t)); 879*a93a1f58Sgm209912 if (new_media == NULL) { 880*a93a1f58Sgm209912 *p_error |= SDP_MEMORY_ERROR; 881*a93a1f58Sgm209912 return (NULL); 882*a93a1f58Sgm209912 } 883*a93a1f58Sgm209912 new_media->m_session = session; 884*a93a1f58Sgm209912 /* Get media name */ 885*a93a1f58Sgm209912 current = begin; 886*a93a1f58Sgm209912 if (commp_find_token(&begin, ¤t, end, COMMP_SP, B_FALSE) != 0) { 887*a93a1f58Sgm209912 goto err_ret; 888*a93a1f58Sgm209912 } else { 889*a93a1f58Sgm209912 COMMP_COPY_STR(new_media->m_name, begin, current - begin); 890*a93a1f58Sgm209912 if (new_media->m_name == NULL) { 891*a93a1f58Sgm209912 sdp_free_media(new_media); 892*a93a1f58Sgm209912 *p_error |= SDP_MEMORY_ERROR; 893*a93a1f58Sgm209912 return (NULL); 894*a93a1f58Sgm209912 } 895*a93a1f58Sgm209912 } 896*a93a1f58Sgm209912 /* Get port */ 897*a93a1f58Sgm209912 begin = ++current; 898*a93a1f58Sgm209912 if (commp_find_token(&begin, ¤t, end, COMMP_SP, B_FALSE) != 0) 899*a93a1f58Sgm209912 goto err_ret; 900*a93a1f58Sgm209912 fake_end = current; 901*a93a1f58Sgm209912 current = begin; 902*a93a1f58Sgm209912 if (commp_find_token(&begin, ¤t, fake_end, COMMP_SLASH, 903*a93a1f58Sgm209912 B_FALSE) != 0) { 904*a93a1f58Sgm209912 goto err_ret; 905*a93a1f58Sgm209912 } 906*a93a1f58Sgm209912 if (commp_atoui(begin, current, &new_media->m_port) != 0) 907*a93a1f58Sgm209912 goto err_ret; 908*a93a1f58Sgm209912 /* Get portcount */ 909*a93a1f58Sgm209912 if (*current == COMMP_SLASH) { 910*a93a1f58Sgm209912 begin = ++current; 911*a93a1f58Sgm209912 if (commp_find_token(&begin, ¤t, fake_end, COMMP_SP, 912*a93a1f58Sgm209912 B_FALSE) != 0) { 913*a93a1f58Sgm209912 goto err_ret; 914*a93a1f58Sgm209912 } 915*a93a1f58Sgm209912 if (commp_atoi(begin, current, &new_media->m_portcount) != 0) 916*a93a1f58Sgm209912 goto err_ret; 917*a93a1f58Sgm209912 } else { 918*a93a1f58Sgm209912 new_media->m_portcount = 1; 919*a93a1f58Sgm209912 } 920*a93a1f58Sgm209912 /* Get Protocol */ 921*a93a1f58Sgm209912 begin = ++current; 922*a93a1f58Sgm209912 if (commp_find_token(&begin, ¤t, end, COMMP_SP, B_FALSE) != 0) { 923*a93a1f58Sgm209912 goto err_ret; 924*a93a1f58Sgm209912 } else { 925*a93a1f58Sgm209912 COMMP_COPY_STR(new_media->m_proto, begin, current - begin); 926*a93a1f58Sgm209912 if (new_media->m_proto == NULL) { 927*a93a1f58Sgm209912 sdp_free_media(new_media); 928*a93a1f58Sgm209912 *p_error |= SDP_MEMORY_ERROR; 929*a93a1f58Sgm209912 return (NULL); 930*a93a1f58Sgm209912 } 931*a93a1f58Sgm209912 } 932*a93a1f58Sgm209912 ++current; 933*a93a1f58Sgm209912 /* Get format list */ 934*a93a1f58Sgm209912 if (current >= end) 935*a93a1f58Sgm209912 goto err_ret; 936*a93a1f58Sgm209912 while (current < end) { 937*a93a1f58Sgm209912 begin = current; 938*a93a1f58Sgm209912 if (commp_find_token(&begin, ¤t, end, COMMP_SP, 939*a93a1f58Sgm209912 B_FALSE) != 0) { 940*a93a1f58Sgm209912 goto err_ret; 941*a93a1f58Sgm209912 } 942*a93a1f58Sgm209912 if (add_value_to_list(&new_media->m_format, begin, 943*a93a1f58Sgm209912 current - begin, B_TRUE) != 0) { 944*a93a1f58Sgm209912 sdp_free_media(new_media); 945*a93a1f58Sgm209912 *p_error |= SDP_MEMORY_ERROR; 946*a93a1f58Sgm209912 return (NULL); 947*a93a1f58Sgm209912 } 948*a93a1f58Sgm209912 ++current; 949*a93a1f58Sgm209912 } 950*a93a1f58Sgm209912 /* check for trailing white space character. */ 951*a93a1f58Sgm209912 if (isspace(*(end - 1))) 952*a93a1f58Sgm209912 goto err_ret; 953*a93a1f58Sgm209912 /* Assign new media to the media list */ 954*a93a1f58Sgm209912 tmp = session->s_media; 955*a93a1f58Sgm209912 if (tmp == NULL) { 956*a93a1f58Sgm209912 session->s_media = new_media; 957*a93a1f58Sgm209912 } else { 958*a93a1f58Sgm209912 while (tmp->m_next != NULL) 959*a93a1f58Sgm209912 tmp = tmp->m_next; 960*a93a1f58Sgm209912 tmp->m_next = new_media; 961*a93a1f58Sgm209912 } 962*a93a1f58Sgm209912 return (new_media); 963*a93a1f58Sgm209912 err_ret: 964*a93a1f58Sgm209912 *p_error |= SDP_MEDIA_ERROR; 965*a93a1f58Sgm209912 sdp_free_media(new_media); 966*a93a1f58Sgm209912 return (NULL); 967*a93a1f58Sgm209912 } 968*a93a1f58Sgm209912 969*a93a1f58Sgm209912 /* 970*a93a1f58Sgm209912 * This function ensures that a field is in the right order in SDP descripton. 971*a93a1f58Sgm209912 * It also identifies cases where a field ('v', 'o, 'i', et al) that must occur 972*a93a1f58Sgm209912 * once but occurs several times in SDP description. error cannot be NULL. 973*a93a1f58Sgm209912 */ 974*a93a1f58Sgm209912 static void 975*a93a1f58Sgm209912 sdp_check_order(char prev, char *order, int *error) 976*a93a1f58Sgm209912 { 977*a93a1f58Sgm209912 *error = 0; 978*a93a1f58Sgm209912 while (*order != '\0') { 979*a93a1f58Sgm209912 if (*order++ == prev) 980*a93a1f58Sgm209912 return; 981*a93a1f58Sgm209912 } 982*a93a1f58Sgm209912 *error = 1; 983*a93a1f58Sgm209912 } 984*a93a1f58Sgm209912 985*a93a1f58Sgm209912 /* 986*a93a1f58Sgm209912 * This function determines the SDP field and calls the appropriate parse 987*a93a1f58Sgm209912 * function. It also ensures that the SDP fields are in strict order. 988*a93a1f58Sgm209912 */ 989*a93a1f58Sgm209912 static void 990*a93a1f58Sgm209912 sdp_handle_fields(sdp_description_t *description, sdp_session_t *_session, 991*a93a1f58Sgm209912 const char *begin, const char *end) 992*a93a1f58Sgm209912 { 993*a93a1f58Sgm209912 boolean_t u_field = B_FALSE; 994*a93a1f58Sgm209912 int error = 0; /* fields order error */ 995*a93a1f58Sgm209912 char prev = description->d_prev; 996*a93a1f58Sgm209912 char m_prev = description->d_mprev; 997*a93a1f58Sgm209912 998*a93a1f58Sgm209912 switch (*begin) { 999*a93a1f58Sgm209912 case SDP_VERSION_FIELD: 1000*a93a1f58Sgm209912 sdp_check_order(prev, SDP_VERSION_ORDER, &error); 1001*a93a1f58Sgm209912 description->d_version = B_TRUE; 1002*a93a1f58Sgm209912 sdp_parse_version(&_session->s_version, begin + 1, end, 1003*a93a1f58Sgm209912 &description->d_perror); 1004*a93a1f58Sgm209912 break; 1005*a93a1f58Sgm209912 case SDP_ORIGIN_FIELD: 1006*a93a1f58Sgm209912 sdp_check_order(prev, SDP_ORIGIN_ORDER, &error); 1007*a93a1f58Sgm209912 description->d_origin = B_TRUE; 1008*a93a1f58Sgm209912 sdp_parse_origin(&_session->s_origin, begin + 1, end, 1009*a93a1f58Sgm209912 &description->d_perror); 1010*a93a1f58Sgm209912 break; 1011*a93a1f58Sgm209912 case SDP_NAME_FIELD: 1012*a93a1f58Sgm209912 sdp_check_order(prev, SDP_NAME_ORDER, &error); 1013*a93a1f58Sgm209912 description->d_name = B_TRUE; 1014*a93a1f58Sgm209912 sdp_parse_name(&_session->s_name, begin + 1, end, 1015*a93a1f58Sgm209912 &description->d_perror); 1016*a93a1f58Sgm209912 break; 1017*a93a1f58Sgm209912 case SDP_INFO_FIELD: 1018*a93a1f58Sgm209912 if (description->d_mparsed) { 1019*a93a1f58Sgm209912 sdp_check_order(m_prev, SDP_M_INFO_ORDER, 1020*a93a1f58Sgm209912 &error); 1021*a93a1f58Sgm209912 if (description->d_lmedia == NULL) 1022*a93a1f58Sgm209912 break; 1023*a93a1f58Sgm209912 sdp_parse_info(&(description->d_lmedia-> 1024*a93a1f58Sgm209912 m_info), begin + 1, end, &description-> 1025*a93a1f58Sgm209912 d_perror); 1026*a93a1f58Sgm209912 } else { 1027*a93a1f58Sgm209912 sdp_check_order(prev, SDP_INFO_ORDER, &error); 1028*a93a1f58Sgm209912 sdp_parse_info(&_session->s_info, begin + 1, 1029*a93a1f58Sgm209912 end, &description->d_perror); 1030*a93a1f58Sgm209912 } 1031*a93a1f58Sgm209912 break; 1032*a93a1f58Sgm209912 case SDP_URI_FIELD: 1033*a93a1f58Sgm209912 sdp_check_order(prev, SDP_URI_ORDER, &error); 1034*a93a1f58Sgm209912 sdp_parse_uri(&_session->s_uri, begin + 1, end, 1035*a93a1f58Sgm209912 &description->d_perror); 1036*a93a1f58Sgm209912 break; 1037*a93a1f58Sgm209912 case SDP_EMAIL_FIELD: 1038*a93a1f58Sgm209912 sdp_check_order(prev, SDP_EMAIL_ORDER, &error); 1039*a93a1f58Sgm209912 sdp_parse_email(&_session->s_email, begin + 1, end, 1040*a93a1f58Sgm209912 &description->d_perror); 1041*a93a1f58Sgm209912 break; 1042*a93a1f58Sgm209912 case SDP_PHONE_FIELD: 1043*a93a1f58Sgm209912 sdp_check_order(prev, SDP_PHONE_ORDER, &error); 1044*a93a1f58Sgm209912 sdp_parse_phone(&_session->s_phone, begin + 1, end, 1045*a93a1f58Sgm209912 &description->d_perror); 1046*a93a1f58Sgm209912 break; 1047*a93a1f58Sgm209912 case SDP_CONNECTION_FIELD: 1048*a93a1f58Sgm209912 if (description->d_mparsed) { 1049*a93a1f58Sgm209912 sdp_check_order(m_prev, SDP_M_CONN_ORDER, 1050*a93a1f58Sgm209912 &error); 1051*a93a1f58Sgm209912 --description->d_mccount; 1052*a93a1f58Sgm209912 if (description->d_lmedia == NULL) 1053*a93a1f58Sgm209912 break; 1054*a93a1f58Sgm209912 sdp_parse_connection(&(description->d_lmedia-> 1055*a93a1f58Sgm209912 m_conn), begin + 1, end, 1056*a93a1f58Sgm209912 &description->d_perror); 1057*a93a1f58Sgm209912 } else { 1058*a93a1f58Sgm209912 /* 1059*a93a1f58Sgm209912 * RFC - 4566 says that session section should 1060*a93a1f58Sgm209912 * have only one connection field, while media 1061*a93a1f58Sgm209912 * section can have many 1062*a93a1f58Sgm209912 */ 1063*a93a1f58Sgm209912 sdp_check_order(prev, SDP_CONN_ORDER, &error); 1064*a93a1f58Sgm209912 description->d_conn = B_TRUE; 1065*a93a1f58Sgm209912 if (_session->s_conn != NULL) 1066*a93a1f58Sgm209912 break; 1067*a93a1f58Sgm209912 sdp_parse_connection(&_session->s_conn, 1068*a93a1f58Sgm209912 begin + 1, end, &description->d_perror); 1069*a93a1f58Sgm209912 } 1070*a93a1f58Sgm209912 break; 1071*a93a1f58Sgm209912 case SDP_BANDWIDTH_FIELD: 1072*a93a1f58Sgm209912 if (description->d_mparsed) { 1073*a93a1f58Sgm209912 sdp_check_order(m_prev, SDP_M_BW_ORDER, &error); 1074*a93a1f58Sgm209912 if (description->d_lmedia == NULL) 1075*a93a1f58Sgm209912 break; 1076*a93a1f58Sgm209912 sdp_parse_bandwidth(&(description->d_lmedia-> 1077*a93a1f58Sgm209912 m_bw), begin + 1, end, 1078*a93a1f58Sgm209912 &description->d_perror); 1079*a93a1f58Sgm209912 } else { 1080*a93a1f58Sgm209912 sdp_check_order(prev, SDP_BW_ORDER, &error); 1081*a93a1f58Sgm209912 sdp_parse_bandwidth(&_session->s_bw, 1082*a93a1f58Sgm209912 begin + 1, end, &description->d_perror); 1083*a93a1f58Sgm209912 } 1084*a93a1f58Sgm209912 break; 1085*a93a1f58Sgm209912 case SDP_TIME_FIELD: 1086*a93a1f58Sgm209912 if (!description->d_tparsed || description->d_prev != 1087*a93a1f58Sgm209912 SDP_REPEAT_FIELD) { 1088*a93a1f58Sgm209912 sdp_check_order(prev, SDP_TIME_ORDER, &error); 1089*a93a1f58Sgm209912 } 1090*a93a1f58Sgm209912 description->d_tparsed = B_TRUE; 1091*a93a1f58Sgm209912 description->d_ltime = sdp_parse_time(&_session-> 1092*a93a1f58Sgm209912 s_time, begin + 1, end, &description->d_perror); 1093*a93a1f58Sgm209912 break; 1094*a93a1f58Sgm209912 case SDP_REPEAT_FIELD: 1095*a93a1f58Sgm209912 sdp_check_order(prev, SDP_REPEAT_ORDER, &error); 1096*a93a1f58Sgm209912 if (description->d_ltime == NULL) 1097*a93a1f58Sgm209912 break; 1098*a93a1f58Sgm209912 /* we pass time, as repeat is associated with time */ 1099*a93a1f58Sgm209912 sdp_parse_repeat(description->d_ltime, begin + 1, end, 1100*a93a1f58Sgm209912 &description->d_perror); 1101*a93a1f58Sgm209912 break; 1102*a93a1f58Sgm209912 case SDP_ZONE_FIELD: 1103*a93a1f58Sgm209912 sdp_check_order(prev, SDP_ZONE_ORDER, &error); 1104*a93a1f58Sgm209912 sdp_parse_zone(&_session->s_zone, begin + 1, end, 1105*a93a1f58Sgm209912 &description->d_perror); 1106*a93a1f58Sgm209912 break; 1107*a93a1f58Sgm209912 case SDP_KEY_FIELD: 1108*a93a1f58Sgm209912 if (description->d_mparsed) { 1109*a93a1f58Sgm209912 sdp_check_order(m_prev, SDP_M_KEY_ORDER, 1110*a93a1f58Sgm209912 &error); 1111*a93a1f58Sgm209912 if (description->d_lmedia == NULL) 1112*a93a1f58Sgm209912 break; 1113*a93a1f58Sgm209912 sdp_parse_key(&(description->d_lmedia->m_key), 1114*a93a1f58Sgm209912 begin + 1, end, &description->d_perror); 1115*a93a1f58Sgm209912 } else { 1116*a93a1f58Sgm209912 sdp_check_order(prev, SDP_KEY_ORDER, &error); 1117*a93a1f58Sgm209912 sdp_parse_key(&_session->s_key, begin + 1, end, 1118*a93a1f58Sgm209912 &description->d_perror); 1119*a93a1f58Sgm209912 } 1120*a93a1f58Sgm209912 break; 1121*a93a1f58Sgm209912 case SDP_ATTRIBUTE_FIELD: 1122*a93a1f58Sgm209912 if (description->d_mparsed) { 1123*a93a1f58Sgm209912 sdp_check_order(m_prev, SDP_M_ATTR_ORDER, 1124*a93a1f58Sgm209912 &error); 1125*a93a1f58Sgm209912 if (description->d_lmedia == NULL) 1126*a93a1f58Sgm209912 break; 1127*a93a1f58Sgm209912 sdp_parse_attribute(&(description->d_lmedia-> 1128*a93a1f58Sgm209912 m_attr), begin + 1, end, 1129*a93a1f58Sgm209912 &description->d_perror); 1130*a93a1f58Sgm209912 } else { 1131*a93a1f58Sgm209912 sdp_check_order(prev, SDP_ATTR_ORDER, &error); 1132*a93a1f58Sgm209912 sdp_parse_attribute(&_session->s_attr, 1133*a93a1f58Sgm209912 begin + 1, end, &description->d_perror); 1134*a93a1f58Sgm209912 } 1135*a93a1f58Sgm209912 break; 1136*a93a1f58Sgm209912 case SDP_MEDIA_FIELD: 1137*a93a1f58Sgm209912 if (!description->d_mparsed) { 1138*a93a1f58Sgm209912 sdp_check_order(prev, SDP_MEDIA_ORDER, &error); 1139*a93a1f58Sgm209912 description->d_mccount = 1; 1140*a93a1f58Sgm209912 } else { 1141*a93a1f58Sgm209912 if (description->d_mccount == 1) 1142*a93a1f58Sgm209912 description->d_mconn = B_FALSE; 1143*a93a1f58Sgm209912 description->d_mccount = 1; 1144*a93a1f58Sgm209912 } 1145*a93a1f58Sgm209912 description->d_mparsed = B_TRUE; 1146*a93a1f58Sgm209912 description->d_lmedia = sdp_parse_media(_session, 1147*a93a1f58Sgm209912 begin + 1, end, &description->d_perror); 1148*a93a1f58Sgm209912 break; 1149*a93a1f58Sgm209912 default: 1150*a93a1f58Sgm209912 /* Unknown field type. Ignore it */ 1151*a93a1f58Sgm209912 u_field = B_TRUE; 1152*a93a1f58Sgm209912 break; 1153*a93a1f58Sgm209912 } 1154*a93a1f58Sgm209912 if (error) 1155*a93a1f58Sgm209912 description->d_perror |= SDP_FIELDS_ORDER_ERROR; 1156*a93a1f58Sgm209912 if (!u_field) { 1157*a93a1f58Sgm209912 if (!description->d_mparsed) 1158*a93a1f58Sgm209912 description->d_prev = *begin; 1159*a93a1f58Sgm209912 else 1160*a93a1f58Sgm209912 description->d_mprev = *begin; 1161*a93a1f58Sgm209912 } 1162*a93a1f58Sgm209912 } 1163*a93a1f58Sgm209912 1164*a93a1f58Sgm209912 /* 1165*a93a1f58Sgm209912 * Parses the SDP info 1166*a93a1f58Sgm209912 */ 1167*a93a1f58Sgm209912 int 1168*a93a1f58Sgm209912 sdp_parse(const char *sdp_info, int len, int flags, sdp_session_t **session, 1169*a93a1f58Sgm209912 uint_t *p_error) 1170*a93a1f58Sgm209912 { 1171*a93a1f58Sgm209912 1172*a93a1f58Sgm209912 const char *f_begin; 1173*a93a1f58Sgm209912 const char *f_end; 1174*a93a1f58Sgm209912 sdp_description_t *description; 1175*a93a1f58Sgm209912 const char *start; 1176*a93a1f58Sgm209912 const char *end; 1177*a93a1f58Sgm209912 const char *current; 1178*a93a1f58Sgm209912 1179*a93a1f58Sgm209912 if (sdp_info == NULL || len == 0 || p_error == NULL || flags != 0 || 1180*a93a1f58Sgm209912 session == NULL) { 1181*a93a1f58Sgm209912 if (session != NULL) 1182*a93a1f58Sgm209912 *session = NULL; 1183*a93a1f58Sgm209912 return (EINVAL); 1184*a93a1f58Sgm209912 } 1185*a93a1f58Sgm209912 *session = NULL; 1186*a93a1f58Sgm209912 *p_error = 0; 1187*a93a1f58Sgm209912 description = calloc(1, sizeof (sdp_description_t)); 1188*a93a1f58Sgm209912 if (description == NULL) { 1189*a93a1f58Sgm209912 return (ENOMEM); 1190*a93a1f58Sgm209912 } 1191*a93a1f58Sgm209912 /* Needed later to check for mandatory fields */ 1192*a93a1f58Sgm209912 description->d_prev = COMMP_SP; 1193*a93a1f58Sgm209912 description->d_mconn = B_TRUE; 1194*a93a1f58Sgm209912 *session = sdp_new_session(); 1195*a93a1f58Sgm209912 if (*session == NULL) { 1196*a93a1f58Sgm209912 free(description); 1197*a93a1f58Sgm209912 return (ENOMEM); 1198*a93a1f58Sgm209912 } 1199*a93a1f58Sgm209912 start = sdp_info; 1200*a93a1f58Sgm209912 end = start + len; 1201*a93a1f58Sgm209912 if (commp_skip_white_space(&start, end) != 0) { 1202*a93a1f58Sgm209912 free(description); 1203*a93a1f58Sgm209912 free(*session); 1204*a93a1f58Sgm209912 *session = NULL; 1205*a93a1f58Sgm209912 return (EINVAL); 1206*a93a1f58Sgm209912 } 1207*a93a1f58Sgm209912 current = start; 1208*a93a1f58Sgm209912 f_begin = current; 1209*a93a1f58Sgm209912 while ((current < end) && !(description->d_perror & 1210*a93a1f58Sgm209912 SDP_MEMORY_ERROR)) { 1211*a93a1f58Sgm209912 /* 1212*a93a1f58Sgm209912 * RFC says parser SHOULD be tolerant to records ending 1213*a93a1f58Sgm209912 * with a single newline character too. 1214*a93a1f58Sgm209912 */ 1215*a93a1f58Sgm209912 if (strncmp(COMMP_CRLF, current, strlen(COMMP_CRLF)) == 0) { 1216*a93a1f58Sgm209912 f_end = current; 1217*a93a1f58Sgm209912 sdp_handle_fields(description, *session, f_begin, 1218*a93a1f58Sgm209912 f_end); 1219*a93a1f58Sgm209912 COMMP_SKIP_CRLF(current); 1220*a93a1f58Sgm209912 (void) commp_skip_white_space(¤t, end); 1221*a93a1f58Sgm209912 f_begin = current; 1222*a93a1f58Sgm209912 } else if (strncmp(COMMP_LF, current, strlen(COMMP_LF)) == 0) { 1223*a93a1f58Sgm209912 f_end = current; 1224*a93a1f58Sgm209912 sdp_handle_fields(description, *session, f_begin, 1225*a93a1f58Sgm209912 f_end); 1226*a93a1f58Sgm209912 COMMP_SKIP_LF(current); 1227*a93a1f58Sgm209912 (void) commp_skip_white_space(¤t, end); 1228*a93a1f58Sgm209912 f_begin = current; 1229*a93a1f58Sgm209912 } else { 1230*a93a1f58Sgm209912 current++; 1231*a93a1f58Sgm209912 } 1232*a93a1f58Sgm209912 } 1233*a93a1f58Sgm209912 if (description->d_perror & SDP_MEMORY_ERROR) { 1234*a93a1f58Sgm209912 free(description); 1235*a93a1f58Sgm209912 sdp_free_session(*session); 1236*a93a1f58Sgm209912 *session = NULL; 1237*a93a1f58Sgm209912 return (ENOMEM); 1238*a93a1f58Sgm209912 } 1239*a93a1f58Sgm209912 /* 1240*a93a1f58Sgm209912 * Check for mandatory fields v, o, s, t fields. For connection field, 1241*a93a1f58Sgm209912 * RFC says; a connection field must be present in every media 1242*a93a1f58Sgm209912 * description or at the session-level 1243*a93a1f58Sgm209912 */ 1244*a93a1f58Sgm209912 if (description->d_mccount == 1) 1245*a93a1f58Sgm209912 description->d_mconn = B_FALSE; 1246*a93a1f58Sgm209912 if (!(description->d_version && description->d_origin && 1247*a93a1f58Sgm209912 description->d_name && description->d_tparsed && 1248*a93a1f58Sgm209912 (description->d_conn || (description->d_mparsed && 1249*a93a1f58Sgm209912 description->d_mconn)))) { 1250*a93a1f58Sgm209912 description->d_perror |= SDP_MISSING_FIELDS; 1251*a93a1f58Sgm209912 } 1252*a93a1f58Sgm209912 *p_error = description->d_perror; 1253*a93a1f58Sgm209912 free(description); 1254*a93a1f58Sgm209912 return (0); 1255*a93a1f58Sgm209912 } 1256