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