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