1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * Helper functions to skip white spaces, find tokens, find separators and free 31 * memory. 32 */ 33 34 #include <stdio.h> 35 #include <assert.h> 36 #include <errno.h> 37 #include <stdlib.h> 38 #include <string.h> 39 #include <ctype.h> 40 #include <sdp.h> 41 42 #include "sdp_parse.h" 43 #include "commp_util.h" 44 45 void 46 sdp_free_origin(sdp_origin_t *origin) 47 { 48 if (origin != NULL) { 49 if (origin->o_username != NULL) 50 free(origin->o_username); 51 if (origin->o_nettype != NULL) 52 free(origin->o_nettype); 53 if (origin->o_addrtype != NULL) 54 free(origin->o_addrtype); 55 if (origin->o_address != NULL) 56 free(origin->o_address); 57 free(origin); 58 } 59 } 60 61 void 62 sdp_free_key(sdp_key_t *key) 63 { 64 if (key != NULL) { 65 if (key->k_method != NULL) 66 free(key->k_method); 67 if (key->k_enckey != NULL) 68 free(key->k_enckey); 69 free(key); 70 } 71 } 72 73 void 74 sdp_free_zone(sdp_zone_t *zone) 75 { 76 sdp_zone_t *next_zone; 77 78 while (zone != NULL) { 79 next_zone = zone->z_next; 80 if (zone->z_offset != NULL) 81 free(zone->z_offset); 82 free(zone); 83 zone = next_zone; 84 } 85 } 86 87 void 88 sdp_free_list(sdp_list_t *list) 89 { 90 sdp_list_t *next_list; 91 92 while (list != NULL) { 93 next_list = list->next; 94 if (list->value != NULL) 95 free(list->value); 96 free(list); 97 list = next_list; 98 } 99 } 100 101 void 102 sdp_free_media(sdp_media_t *media) 103 { 104 sdp_media_t *next_media; 105 106 while (media != NULL) { 107 next_media = media->m_next; 108 if (media->m_name != NULL) 109 free(media->m_name); 110 if (media->m_proto != NULL) 111 free(media->m_proto); 112 if (media->m_format != NULL) 113 sdp_free_list(media->m_format); 114 if (media->m_info != NULL) 115 free(media->m_info); 116 if (media->m_conn != NULL) 117 sdp_free_connection(media->m_conn); 118 if (media->m_bw != NULL) 119 sdp_free_bandwidth(media->m_bw); 120 if (media->m_key != NULL) 121 sdp_free_key(media->m_key); 122 if (media->m_attr != NULL) 123 sdp_free_attribute(media->m_attr); 124 free(media); 125 media = next_media; 126 } 127 } 128 129 void 130 sdp_free_attribute(sdp_attr_t *attr) 131 { 132 sdp_attr_t *next_attr; 133 134 while (attr != NULL) { 135 next_attr = attr->a_next; 136 if (attr->a_name != NULL) 137 free(attr->a_name); 138 if (attr->a_value != NULL) 139 free(attr->a_value); 140 free(attr); 141 attr = next_attr; 142 } 143 } 144 145 void 146 sdp_free_connection(sdp_conn_t *conn) 147 { 148 sdp_conn_t *next_conn; 149 150 while (conn != NULL) { 151 next_conn = conn->c_next; 152 if (conn->c_nettype != NULL) 153 free(conn->c_nettype); 154 if (conn->c_addrtype != NULL) 155 free(conn->c_addrtype); 156 if (conn->c_address != NULL) 157 free(conn->c_address); 158 free(conn); 159 conn = next_conn; 160 } 161 } 162 163 void 164 sdp_free_bandwidth(sdp_bandwidth_t *bw) 165 { 166 sdp_bandwidth_t *next_bw; 167 168 while (bw != NULL) { 169 next_bw = bw->b_next; 170 if (bw->b_type != NULL) 171 free(bw->b_type); 172 free(bw); 173 bw = next_bw; 174 } 175 } 176 177 void 178 sdp_free_repeat(sdp_repeat_t *repeat) 179 { 180 sdp_repeat_t *next_repeat; 181 182 while (repeat != NULL) { 183 next_repeat = repeat->r_next; 184 sdp_free_list(repeat->r_offset); 185 free(repeat); 186 repeat = next_repeat; 187 } 188 } 189 190 void 191 sdp_free_time(sdp_time_t *time) 192 { 193 sdp_time_t *next_time; 194 195 while (time != NULL) { 196 next_time = time->t_next; 197 sdp_free_repeat(time->t_repeat); 198 free(time); 199 time = next_time; 200 } 201 } 202 203 void 204 sdp_free_session(sdp_session_t *session) 205 { 206 if (session == NULL) 207 return; 208 if (session->s_origin != NULL) 209 sdp_free_origin(session->s_origin); 210 if (session->s_name != NULL) 211 free(session->s_name); 212 if (session->s_info != NULL) 213 free(session->s_info); 214 if (session->s_uri != NULL) 215 free(session->s_uri); 216 if (session->s_email != NULL) 217 sdp_free_list(session->s_email); 218 if (session->s_phone != NULL) 219 sdp_free_list(session->s_phone); 220 if (session->s_conn != NULL) 221 sdp_free_connection(session->s_conn); 222 if (session->s_bw != NULL) 223 sdp_free_bandwidth(session->s_bw); 224 if (session->s_time != NULL) 225 sdp_free_time(session->s_time); 226 if (session->s_zone != NULL) 227 sdp_free_zone(session->s_zone); 228 if (session->s_key != NULL) 229 sdp_free_key(session->s_key); 230 if (session->s_attr != NULL) 231 sdp_free_attribute(session->s_attr); 232 if (session->s_media != NULL) 233 sdp_free_media(session->s_media); 234 free(session); 235 } 236 237 /* 238 * Adds text of a given length to a linked list. If the list is NULL to 239 * start with it builds the new list 240 */ 241 int 242 add_value_to_list(sdp_list_t **list, const char *value, int len, boolean_t text) 243 { 244 sdp_list_t *new = NULL; 245 sdp_list_t *tmp = NULL; 246 247 new = malloc(sizeof (sdp_list_t)); 248 if (new == NULL) 249 return (ENOMEM); 250 new->next = NULL; 251 if (text) 252 new->value = (char *)calloc(1, len + 1); 253 else 254 new->value = (uint64_t *)calloc(1, sizeof (uint64_t)); 255 if (new->value == NULL) { 256 free(new); 257 return (ENOMEM); 258 } 259 if (text) { 260 (void) strncpy(new->value, value, len); 261 } else { 262 if (commp_time_to_secs((char *)value, (char *)(value + 263 len), new->value) != 0) { 264 sdp_free_list(new); 265 return (EINVAL); 266 } 267 } 268 if (*list == NULL) { 269 *list = new; 270 } else { 271 tmp = *list; 272 while (tmp->next != NULL) 273 tmp = tmp->next; 274 tmp->next = new; 275 } 276 return (0); 277 } 278 279 /* 280 * Given a linked list converts it to space separated string. 281 */ 282 int 283 sdp_list_to_str(sdp_list_t *list, char **buf, boolean_t text) 284 { 285 int size = 0; 286 int wrote = 0; 287 sdp_list_t *tmp; 288 char *ret; 289 char c[1]; 290 291 if (list == NULL) { 292 *buf = NULL; 293 return (EINVAL); 294 } 295 tmp = list; 296 while (list != NULL) { 297 if (text) 298 size += strlen((char *)list->value); 299 else 300 size += snprintf(c, 1, "%lld", 301 *(uint64_t *)list->value); 302 size++; 303 list = list->next; 304 } 305 list = tmp; 306 if (size > 0) { 307 *buf = calloc(1, size + 1); 308 if (*buf == NULL) 309 return (ENOMEM); 310 ret = *buf; 311 while (list != NULL) { 312 if (text) { 313 wrote = snprintf(ret, size, "%s ", 314 (char *)list->value); 315 } else { 316 wrote = snprintf(ret, size, "%lld ", 317 *(uint64_t *)list->value); 318 } 319 ret = ret + wrote; 320 size = size - wrote; 321 list = list->next; 322 } 323 } else { 324 return (EINVAL); 325 } 326 return (0); 327 } 328 329 /* 330 * Given a space separated string, converts it into linked list. SDP field 331 * repeat and media can have undefined number of offsets or formats 332 * respectively. We need to capture it in a linked list. 333 */ 334 int 335 sdp_str_to_list(sdp_list_t **list, const char *buf, int len, boolean_t text) 336 { 337 const char *begin; 338 const char *current; 339 const char *end; 340 int ret = 0; 341 342 if (len == 0) 343 return (EINVAL); 344 current = buf; 345 end = current + len; 346 /* takes care of strings with just spaces */ 347 if (commp_skip_white_space(¤t, end) != 0) 348 return (EINVAL); 349 while (current < end) { 350 (void) commp_skip_white_space(¤t, end); 351 begin = current; 352 while (current < end) { 353 if (isspace(*current)) 354 break; 355 ++current; 356 } 357 if (current != begin) { 358 if ((ret = add_value_to_list(list, begin, 359 current - begin, text)) != 0) { 360 sdp_free_list(*list); 361 *list = NULL; 362 return (ret); 363 } 364 } 365 } 366 return (0); 367 } 368