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