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#include <stdlib.h>
27#include <string.h>
28#include <ctype.h>
29#include <errno.h>
30
31#include "sip_parse_uri.h"
32
33void
34sip_free_parsed_uri(sip_uri_t uri)
35{
36	_sip_uri_t	*_uri;
37
38	if (uri == NULL)
39		return;
40
41	_uri = (_sip_uri_t *)uri;
42	if (_uri->sip_uri_issip) {
43		sip_param_t	*param;
44		sip_param_t	*param_next;
45
46		param = _uri->sip_uri_params;
47		while (param != NULL) {
48			param_next = param->param_next;
49			free(param);
50			param = param_next;
51		}
52	}
53	free(_uri);
54}
55
56/*
57 * Parse the URI in uri_str
58 */
59struct sip_uri *
60sip_parse_uri(sip_str_t *uri_str, int *error)
61{
62	struct sip_uri	*parsed_uri;
63
64	if (error != NULL)
65		*error = 0;
66
67	if (uri_str == NULL) {
68		if (error != NULL)
69			*error = EINVAL;
70		return (NULL);
71	}
72	parsed_uri = calloc(1, sizeof (_sip_uri_t));
73	if (parsed_uri == NULL) {
74		if (error != NULL)
75			*error = ENOMEM;
76		return (NULL);
77	}
78
79	sip_uri_parse_it(parsed_uri, uri_str);
80	if (parsed_uri->sip_uri_errflags & SIP_URIERR_MEMORY) {
81		free(parsed_uri);
82		if (error != NULL)
83			*error = ENOMEM;
84		return (NULL);
85	}
86	if (parsed_uri->sip_uri_errflags != 0 && error != NULL)
87		*error = EPROTO;
88	return ((sip_uri_t)parsed_uri);
89}
90
91/*
92 * Get parsed URI
93 */
94const struct sip_uri *
95sip_get_uri_parsed(sip_header_value_t value, int *error)
96{
97	const struct sip_uri	*ret = NULL;
98
99	if (error != NULL)
100		*error = 0;
101	if (value == NULL || value->sip_value_parse_uri == NULL ||
102	    value->value_state == SIP_VALUE_DELETED) {
103		if (error != NULL)
104			*error = EINVAL;
105		return (NULL);
106	}
107	ret = value->sip_value_parse_uri;
108	if (ret->sip_uri_errflags != 0 && error != NULL)
109		*error = EINVAL;
110	return ((sip_uri_t)ret);
111}
112
113/*
114 * Return TRUE if this is a SIP URI
115 */
116boolean_t
117sip_is_sipuri(const struct sip_uri *uri)
118{
119	_sip_uri_t	*_uri;
120
121	if (uri == NULL)
122		return (B_FALSE);
123	_uri = (_sip_uri_t *)uri;
124	if ((_uri->sip_uri_errflags & SIP_URIERR_SCHEME) == 0 &&
125	    _uri->sip_uri_scheme.sip_str_len > 0 && _uri->sip_uri_issip) {
126		return (B_TRUE);
127	}
128	return (B_FALSE);
129}
130
131/*
132 * Some common checks
133 */
134static _sip_uri_t *
135sip_check_get_param(const struct sip_uri *uri, int *error)
136{
137	if (error != NULL)
138		*error = 0;
139
140	if (uri == NULL) {
141		if (error != NULL)
142			*error = EINVAL;
143		return (NULL);
144	}
145	return ((_sip_uri_t *)uri);
146}
147
148
149/*
150 * Return the URI scheme
151 */
152const sip_str_t *
153sip_get_uri_scheme(const struct sip_uri *uri, int *error)
154{
155	_sip_uri_t	*_uri;
156
157	_uri = sip_check_get_param(uri, error);
158	if (_uri == NULL)
159		return (NULL);
160
161	if (((_uri->sip_uri_errflags & SIP_URIERR_SCHEME) != 0 ||
162	    _uri->sip_uri_scheme.sip_str_len == 0) && error != NULL) {
163		*error = EINVAL;
164	}
165	if (_uri->sip_uri_scheme.sip_str_len > 0)
166		return (&_uri->sip_uri_scheme);
167	return (NULL);
168}
169
170/*
171 *  Return user name from URI
172 */
173const sip_str_t *
174sip_get_uri_user(const struct sip_uri *uri, int *error)
175{
176	_sip_uri_t	*_uri;
177
178	_uri = sip_check_get_param(uri, error);
179	if (_uri == NULL)
180		return (NULL);
181
182	if ((_uri->sip_uri_errflags & SIP_URIERR_USER) != 0 && error != NULL)
183		*error = EINVAL;
184	if (uri->sip_uri_user.sip_str_len > 0)
185		return (&uri->sip_uri_user);
186	return (NULL);
187}
188
189/*
190 *  Return password from URI
191 */
192const sip_str_t *
193sip_get_uri_password(const struct sip_uri *uri, int *error)
194{
195	_sip_uri_t	*_uri;
196
197	_uri = sip_check_get_param(uri, error);
198	if (_uri == NULL)
199		return (NULL);
200
201	if ((_uri->sip_uri_errflags & SIP_URIERR_PASS) != 0 && error != NULL)
202		*error = EINVAL;
203	if (_uri->sip_uri_password.sip_str_len > 0)
204		return (&_uri->sip_uri_password);
205	return (NULL);
206}
207
208/*
209 * Get host from the URI
210 */
211const sip_str_t *
212sip_get_uri_host(const struct sip_uri *uri, int *error)
213{
214	_sip_uri_t	*_uri;
215
216	_uri = sip_check_get_param(uri, error);
217	if (_uri == NULL)
218		return (NULL);
219
220	if ((_uri->sip_uri_errflags & SIP_URIERR_HOST) != 0 && error != NULL)
221		*error = EINVAL;
222	if (_uri->sip_uri_host.sip_str_len > 0)
223		return (&_uri->sip_uri_host);
224	return (NULL);
225}
226
227/*
228 * Get port from the URI
229 */
230int
231sip_get_uri_port(const struct sip_uri *uri, int *error)
232{
233	_sip_uri_t	*_uri;
234
235	_uri = sip_check_get_param(uri, error);
236	if (_uri == NULL)
237		return (0);
238
239	if ((_uri->sip_uri_errflags & SIP_URIERR_PORT) != 0) {
240		if (error != NULL)
241			*error = EINVAL;
242		return (0);
243	}
244	return (_uri->sip_uri_port);
245}
246
247const sip_param_t *
248sip_get_uri_params(const struct sip_uri *uri, int *error)
249{
250	_sip_uri_t		*_uri;
251
252	_uri = sip_check_get_param(uri, error);
253	if (_uri == NULL)
254		return (NULL);
255
256	if (!_uri->sip_uri_issip) {
257		if (error != NULL)
258			*error = EINVAL;
259		return (NULL);
260	}
261
262	if ((_uri->sip_uri_errflags & SIP_URIERR_PARAM) != 0 && error != NULL)
263		*error = EINVAL;
264	return (_uri->sip_uri_params);
265}
266
267/*
268 * Get headers from the URI
269 */
270const sip_str_t *
271sip_get_uri_headers(const struct sip_uri *uri, int *error)
272{
273	_sip_uri_t	*_uri;
274
275	_uri = sip_check_get_param(uri, error);
276	if (_uri == NULL)
277		return (NULL);
278
279	if (!_uri->sip_uri_issip) {
280		if (error != NULL)
281			*error = EINVAL;
282		return (NULL);
283	}
284	if ((_uri->sip_uri_errflags & SIP_URIERR_HEADER) != 0 && error != NULL)
285		*error = EINVAL;
286	if (_uri->sip_uri_headers.sip_str_len > 0)
287		return (&_uri->sip_uri_headers);
288	return (NULL);
289}
290
291/*
292 *  Return opaque value for an ABS URI
293 */
294const sip_str_t *
295sip_get_uri_opaque(const struct sip_uri *uri, int *error)
296{
297	_sip_uri_t	*_uri;
298
299	_uri = sip_check_get_param(uri, error);
300	if (_uri == NULL)
301		return (NULL);
302
303	if (_uri->sip_uri_issip) {
304		if (error != NULL)
305			*error = EINVAL;
306		return (NULL);
307	}
308	if ((_uri->sip_uri_errflags & SIP_URIERR_OPAQUE) != 0 && error != NULL)
309		*error = EINVAL;
310	if (_uri->sip_uri_opaque.sip_str_len > 0)
311		return (&_uri->sip_uri_opaque);
312	return (NULL);
313}
314
315/*
316 * Return query from an absolute URI
317 */
318const sip_str_t *
319sip_get_uri_query(const struct sip_uri *uri, int *error)
320{
321	_sip_uri_t	*_uri;
322
323	_uri = sip_check_get_param(uri, error);
324	if (_uri == NULL)
325		return (NULL);
326
327	if (_uri->sip_uri_issip) {
328		if (error != NULL)
329			*error = EINVAL;
330		return (NULL);
331	}
332	if ((_uri->sip_uri_errflags & SIP_URIERR_QUERY) != 0 && error != NULL)
333		*error = EINVAL;
334	if (_uri->sip_uri_query.sip_str_len > 0)
335		return (&_uri->sip_uri_query);
336	return (NULL);
337}
338
339/*
340 *  Get path from an assolute URI
341 */
342const sip_str_t *
343sip_get_uri_path(const struct sip_uri *uri, int *error)
344{
345	_sip_uri_t	*_uri;
346
347	_uri = sip_check_get_param(uri, error);
348	if (_uri == NULL)
349		return (NULL);
350
351	if (_uri->sip_uri_issip) {
352		if (error != NULL)
353			*error = EINVAL;
354		return (NULL);
355	}
356	if ((_uri->sip_uri_errflags & SIP_URIERR_PATH) != 0 && error != NULL)
357		*error = EINVAL;
358	if (_uri->sip_uri_path.sip_str_len > 0)
359		return (&_uri->sip_uri_path);
360	return (NULL);
361}
362
363/*
364 * Get the reg-name from absolute URI
365 */
366const sip_str_t	*
367sip_get_uri_regname(const struct sip_uri *uri, int *error)
368{
369	_sip_uri_t	*_uri;
370
371	_uri = sip_check_get_param(uri, error);
372	if (_uri == NULL)
373		return (NULL);
374
375	if (_uri->sip_uri_issip) {
376		if (error != NULL)
377			*error = EINVAL;
378		return (NULL);
379	}
380	if ((_uri->sip_uri_errflags & SIP_URIERR_REGNAME) != 0 && error != NULL)
381		*error = EINVAL;
382	if (_uri->sip_uri_regname.sip_str_len > 0)
383		return (&_uri->sip_uri_regname);
384	return (NULL);
385}
386
387/*
388 * Return TRUE if this is a teluser
389 */
390boolean_t
391sip_is_uri_teluser(const struct sip_uri *uri)
392{
393	_sip_uri_t	*_uri;
394
395	if (uri == NULL)
396		return (B_FALSE);
397
398	_uri = (_sip_uri_t *)uri;
399	return (_uri->sip_uri_isteluser);
400}
401
402int
403sip_get_uri_errflags(const struct sip_uri *uri, int *error)
404{
405	_sip_uri_t	*_uri;
406
407	_uri = sip_check_get_param(uri, error);
408	if (_uri == NULL)
409		return (0);
410	return (_uri->sip_uri_errflags);
411}
412
413/*
414 * the caller is responsible for freeing the returned string
415 */
416char *
417sip_uri_errflags_to_str(int errflags)
418{
419	char	*err_info = NULL;
420
421	if (errflags == 0)
422		return (NULL);
423
424	err_info = (char *)malloc(SIP_URI_BUF_SIZE);
425	if (err_info == NULL)
426		return (NULL);
427
428	if (errflags & SIP_URIERR_NOURI) {
429		(void) strncpy(err_info, "Error : No URI",
430		    strlen("Error : No URI"));
431		err_info[strlen("Error : No URI")] = '\0';
432		return (err_info);
433	}
434
435	(void) strncpy(err_info, "Error(s) in", strlen("Error(s) in"));
436	err_info[strlen("Error(s) in")] = '\0';
437	if (errflags & SIP_URIERR_SCHEME)
438		(void) strncat(err_info, " SCHEME,", strlen(" SCHEME,"));
439	if (errflags & SIP_URIERR_USER)
440		(void) strncat(err_info, " USER,", strlen(" USER,"));
441	if (errflags & SIP_URIERR_PASS)
442		(void) strncat(err_info, " PASSWORD,", strlen(" PASSWORD,"));
443	if (errflags & SIP_URIERR_HOST)
444		(void) strncat(err_info, " HOST,", strlen(" HOST,"));
445	if (errflags & SIP_URIERR_PORT)
446		(void) strncat(err_info, " PORT,", strlen(" PORT,"));
447	if (errflags & SIP_URIERR_PARAM) {
448		(void) strncat(err_info, " PARAMETERS,",
449		    strlen(" PARAMETERS,"));
450	}
451	if (errflags & SIP_URIERR_HEADER)
452		(void) strncat(err_info, " HEADERS,", strlen(" HEADERS,"));
453	if (errflags & SIP_URIERR_OPAQUE)
454		(void) strncat(err_info, " OPAQUE,", strlen(" OPAQUE,"));
455	if (errflags & SIP_URIERR_QUERY)
456		(void) strncat(err_info, " QUERY,", strlen(" QUERY,"));
457	if (errflags & SIP_URIERR_PATH)
458		(void) strncat(err_info, " PATH,", strlen(" PATH,"));
459	if (errflags & SIP_URIERR_REGNAME)
460		(void) strncat(err_info, " REG-NAME,", strlen(" REG-NAME,"));
461	if (strlen(err_info) == strlen("Error(s) in")) {
462		free(err_info);
463		err_info = NULL;
464	} else {
465		err_info[strlen(err_info) - 1] = '\0';
466		(void) strncat(err_info, " part(s)", strlen(" part(s)"));
467	}
468	return (err_info);
469}
470