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