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
sdp_free_origin(sdp_origin_t * origin)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
sdp_free_key(sdp_key_t * key)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
sdp_free_zone(sdp_zone_t * zone)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
sdp_free_list(sdp_list_t * list)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
sdp_free_media(sdp_media_t * media)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
sdp_free_attribute(sdp_attr_t * attr)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
sdp_free_connection(sdp_conn_t * conn)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
sdp_free_bandwidth(sdp_bandwidth_t * bw)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
sdp_free_repeat(sdp_repeat_t * repeat)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
sdp_free_time(sdp_time_t * time)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
sdp_free_session(sdp_session_t * session)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
add_value_to_list(sdp_list_t ** list,const char * value,int len,boolean_t text)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
sdp_list_to_str(sdp_list_t * list,char ** buf,boolean_t text)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
sdp_str_to_list(sdp_list_t ** list,const char * buf,int len,boolean_t text)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