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 
33 void
sip_free_parsed_uri(sip_uri_t uri)34 sip_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  */
59 struct sip_uri *
sip_parse_uri(sip_str_t * uri_str,int * error)60 sip_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  */
94 const struct sip_uri *
sip_get_uri_parsed(sip_header_value_t value,int * error)95 sip_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  */
116 boolean_t
sip_is_sipuri(const struct sip_uri * uri)117 sip_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  */
134 static _sip_uri_t *
sip_check_get_param(const struct sip_uri * uri,int * error)135 sip_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  */
152 const sip_str_t *
sip_get_uri_scheme(const struct sip_uri * uri,int * error)153 sip_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  */
173 const sip_str_t *
sip_get_uri_user(const struct sip_uri * uri,int * error)174 sip_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  */
192 const sip_str_t *
sip_get_uri_password(const struct sip_uri * uri,int * error)193 sip_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  */
211 const sip_str_t *
sip_get_uri_host(const struct sip_uri * uri,int * error)212 sip_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  */
230 int
sip_get_uri_port(const struct sip_uri * uri,int * error)231 sip_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 
247 const sip_param_t *
sip_get_uri_params(const struct sip_uri * uri,int * error)248 sip_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  */
270 const sip_str_t *
sip_get_uri_headers(const struct sip_uri * uri,int * error)271 sip_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  */
294 const sip_str_t *
sip_get_uri_opaque(const struct sip_uri * uri,int * error)295 sip_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  */
318 const sip_str_t *
sip_get_uri_query(const struct sip_uri * uri,int * error)319 sip_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  */
342 const sip_str_t *
sip_get_uri_path(const struct sip_uri * uri,int * error)343 sip_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  */
366 const sip_str_t	*
sip_get_uri_regname(const struct sip_uri * uri,int * error)367 sip_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  */
390 boolean_t
sip_is_uri_teluser(const struct sip_uri * uri)391 sip_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 
402 int
sip_get_uri_errflags(const struct sip_uri * uri,int * error)403 sip_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  */
416 char *
sip_uri_errflags_to_str(int errflags)417 sip_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