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#include <stdio.h>
30#include <stdlib.h>
31#include <strings.h>
32#include <errno.h>
33#include <pthread.h>
34#include <sip.h>
35
36#include "sip_msg.h"
37
38/*
39 * Generic function to get int or string value from a header
40 */
41static void *
42sip_get_val_from_hdr(sip_hdr_value_t *val, int val_type, boolean_t stype,
43    int *error)
44{
45	if (error != NULL)
46		*error = 0;
47
48	if (val == NULL || val->sip_value_state == SIP_VALUE_DELETED) {
49		if (error != NULL)
50			*error = EINVAL;
51		return (NULL);
52	}
53
54	if (val->sip_value_state == SIP_VALUE_BAD)
55		*error = EPROTO;
56
57	switch (val_type) {
58		case (SIP_INT_VAL):
59			return (&(val->int_val));
60		case (SIP_STR_VAL):
61			return (&(val->str_val));
62		case (SIP_STRS_VAL):
63			if (stype == B_TRUE) {
64				if (val->strs_val.s1.sip_str_ptr != NULL)
65					return (&(val->strs_val.s1));
66				return (NULL);
67			}
68			if (val->strs_val.s2.sip_str_ptr != NULL)
69				return (&(val->strs_val.s2));
70			return (NULL);
71		case (SIP_INTSTR_VAL):
72			if (stype == B_TRUE) {
73				if (val->intstr_str.sip_str_ptr != NULL)
74					return (&(val->intstr_str));
75				else
76					return (NULL);
77			}
78			return (&(val->intstr_int));
79		case (SIP_AUTH_VAL):
80			return (&(val->auth_val));
81	}
82	if (error != NULL && *error == 0)
83		*error = EINVAL;
84	return (NULL);
85}
86
87/*
88 * Generic function to get value from a header given the value type and
89 * the string info (for multi-string values).
90 */
91static void *
92sip_get_val_from_msg(sip_msg_t msg, char *hdr_name, int val_type,
93    boolean_t stype, boolean_t empty_val, int *error)
94{
95	const _sip_header_t	*header;
96	sip_hdr_value_t		*value;
97
98	if (error != NULL)
99		*error = 0;
100	if (msg == NULL) {
101		if (error != NULL)
102			*error = EINVAL;
103		return (NULL);
104	}
105
106	header = sip_get_header(msg, hdr_name, NULL, error);
107	if (header == NULL) {
108		if (error != NULL)
109			*error = EINVAL;
110		return (NULL);
111	}
112
113	value = (sip_hdr_value_t *)sip_get_header_value(header, error);
114	if (value == NULL) {
115		if (error != NULL && empty_val == B_FALSE)
116			*error = EPROTO;
117		return (NULL);
118	}
119	return (sip_get_val_from_hdr(value, val_type, stype, error));
120}
121
122/*
123 * Get the URI from the value
124 */
125const sip_str_t *
126sip_get_cftruri_from_val(sip_header_value_t value, int *error)
127{
128	sip_hdr_value_t	*cftrvalue;
129
130	if (error != NULL)
131		*error = 0;
132
133	if (value == NULL || value->value_state == SIP_VALUE_DELETED) {
134		if (error != NULL)
135			*error = EINVAL;
136		return (NULL);
137	}
138	cftrvalue = (sip_hdr_value_t *)value;
139	/*
140	 * If the value is BAD, update error to reflect it.
141	 */
142	if (error != NULL && value->value_state == SIP_VALUE_BAD)
143		*error = EPROTO;
144	return (&cftrvalue->cftr_uri);
145}
146
147/*
148 * Get display name from the value
149 */
150const sip_str_t *
151sip_get_cftrname_from_val(sip_header_value_t value, int *error)
152{
153	sip_hdr_value_t *cftrvalue;
154
155	if (error != NULL)
156		*error = 0;
157	if (value == NULL || value->value_state == SIP_VALUE_DELETED) {
158		if (error != NULL)
159			*error = EINVAL;
160		return (NULL);
161	}
162	cftrvalue = (sip_hdr_value_t *)value;
163	/*
164	 * If the value is BAD, update error to reflect it.
165	 */
166	if (error != NULL && value->value_state == SIP_VALUE_BAD)
167		*error = EPROTO;
168	return (cftrvalue->cftr_name);
169}
170
171/*
172 * Contact header can have more than one value
173 * so we require a value to be passed in to get a value.
174 */
175const sip_str_t *
176sip_get_contact_uri_str(sip_header_value_t value, int *error)
177{
178	return (sip_get_cftruri_from_val(value, error));
179}
180
181/*
182 * Contact header can have more than one value
183 * so we require a value to be passed in to get a value.
184 */
185const sip_str_t *
186sip_get_contact_display_name(sip_header_value_t value, int *error)
187{
188	return (sip_get_cftrname_from_val(value, error));
189}
190
191/*
192 * Route header can have more than one value
193 * so we require a value to be passed in to get a value.
194 */
195const sip_str_t *
196sip_get_route_uri_str(sip_header_value_t value, int *error)
197{
198	return (sip_get_cftruri_from_val(value, error));
199}
200
201/*
202 * Route header can have more than one value
203 * so we require a value to be passed in to get a value.
204 */
205const sip_str_t *
206sip_get_route_display_name(sip_header_value_t value, int *error)
207{
208	return (sip_get_cftrname_from_val(value, error));
209}
210
211/*
212 * Get URI from the SIP message
213 */
214const sip_str_t *
215sip_get_cftruri_from_msg(sip_msg_t sip_msg, int *error, char *hdrname)
216{
217	const sip_hdr_value_t	*value;
218	const struct sip_header	*header;
219
220	if (error != NULL)
221		*error = 0;
222	if (sip_msg == NULL) {
223		if (error != NULL)
224			*error = EINVAL;
225		return (NULL);
226	}
227
228	header = sip_get_header(sip_msg, hdrname, NULL, error);
229	if (header == NULL) {
230		if (error != NULL)
231			*error = EINVAL;
232		return (NULL);
233	}
234
235	value = (sip_hdr_value_t *)sip_get_header_value(header, error);
236	if (value == NULL) {
237		if (error != NULL)
238			*error = EPROTO;
239		return (NULL);
240	}
241	/*
242	 * If the value is BAD, update error to reflect it.
243	 */
244	if (error != NULL && value->sip_value_state == SIP_VALUE_BAD)
245		*error = EPROTO;
246	return (&value->cftr_uri);
247}
248
249/*
250 * Get display name from the SIP message
251 */
252const sip_str_t *
253sip_get_cftrname_from_msg(sip_msg_t sip_msg, int *error, char *hdrname)
254{
255	const sip_hdr_value_t		*value;
256	const struct  sip_header	*header;
257
258	if (error != NULL)
259		*error = 0;
260	if (sip_msg == NULL) {
261		if (error != NULL)
262			*error = EINVAL;
263		return (NULL);
264	}
265	header = sip_get_header(sip_msg, hdrname, NULL, error);
266	if (header == NULL) {
267		if (error != NULL)
268			*error = EINVAL;
269		return (NULL);
270	}
271
272	value = (sip_hdr_value_t *)sip_get_header_value(header, error);
273	if (value == NULL) {
274		if (error != NULL)
275			*error = EPROTO;
276		return (NULL);
277	}
278	/*
279	 * If the value is BAD, update error to reflect it.
280	 */
281	if (error != NULL && value->sip_value_state == SIP_VALUE_BAD)
282		*error = EPROTO;
283	return (value->cftr_name);
284}
285
286/*
287 * Get FROM URI
288 */
289const sip_str_t *
290sip_get_from_uri_str(sip_msg_t sip_msg, int *error)
291{
292	return (sip_get_cftruri_from_msg(sip_msg, error, SIP_FROM));
293}
294
295/*
296 * Get FROM display name
297 */
298const sip_str_t *
299sip_get_from_display_name(sip_msg_t sip_msg, int *error)
300{
301	return (sip_get_cftrname_from_msg(sip_msg, error, SIP_FROM));
302}
303
304/*
305 * Return the FROM tag
306 */
307const sip_str_t *
308sip_get_from_tag(sip_msg_t sip_msg, int *error)
309{
310	const sip_hdr_value_t	*value;
311	const struct sip_header	*header;
312
313	if (error != NULL)
314		*error = 0;
315	if (sip_msg == NULL) {
316		if (error != NULL)
317			*error = EINVAL;
318		return (NULL);
319	}
320	header = sip_get_header(sip_msg, SIP_FROM, NULL, error);
321	if (header == NULL) {
322		if (error != NULL)
323			*error = EINVAL;
324		return (NULL);
325	}
326
327	value = (sip_hdr_value_t *)sip_get_header_value(header, error);
328	if (value == NULL) {
329		if (error != NULL)
330			*error = EPROTO;
331		return (NULL);
332	}
333	/*
334	 * If the value is BAD, update error to reflect it.
335	 */
336	if (error != NULL && value->sip_value_state == SIP_VALUE_BAD)
337		*error = EPROTO;
338	return (sip_get_param_value((sip_header_value_t)value, "tag", error));
339}
340
341/*
342 * Get TO URI
343 */
344const sip_str_t *
345sip_get_to_uri_str(sip_msg_t sip_msg, int *error)
346{
347	return (sip_get_cftruri_from_msg(sip_msg, error, SIP_TO));
348}
349
350/*
351 * Get TO display name
352 */
353const sip_str_t *
354sip_get_to_display_name(sip_msg_t sip_msg, int *error)
355{
356	return (sip_get_cftrname_from_msg(sip_msg, error, SIP_TO));
357}
358
359/*
360 * Get TO tag
361 */
362const sip_str_t *
363sip_get_to_tag(sip_msg_t sip_msg, int *error)
364{
365	const sip_hdr_value_t	*value;
366	const struct sip_header	*header;
367
368	if (error != NULL)
369		*error = 0;
370	if (sip_msg == NULL) {
371		if (error != NULL)
372			*error = EINVAL;
373		return (NULL);
374	}
375	header = sip_get_header(sip_msg, SIP_TO, NULL, error);
376	if (header == NULL) {
377		if (error != NULL)
378			*error = EINVAL;
379		return (NULL);
380	}
381
382	value = (sip_hdr_value_t *)sip_get_header_value(header, error);
383	if (value == NULL) {
384		if (error != NULL)
385			*error = EPROTO;
386		return (NULL);
387	}
388	/*
389	 * If the value is BAD, update error to reflect it.
390	 */
391	if (error != NULL && value->sip_value_state == SIP_VALUE_BAD)
392		*error = EPROTO;
393	return (sip_get_param_value((sip_header_value_t)value, "tag", error));
394}
395
396/*
397 * Return the Call-Id
398 */
399const sip_str_t *
400sip_get_callid(sip_msg_t sip_msg, int *error)
401{
402	sip_str_t	*r;
403
404	r = (sip_str_t *)sip_get_val_from_msg(sip_msg, SIP_CALL_ID, SIP_STR_VAL,
405	    B_FALSE, B_TRUE, error);
406	return (r);
407}
408
409#define	SIP_CSEQ_NUM	1
410#define	SIP_CSEQ_METHOD	2
411
412/*
413 * Get number/method from the CSEQ header
414 */
415static void *
416sip_get_cseq_val(sip_msg_t msg, int type, int *error)
417{
418	const _sip_header_t	*header;
419	sip_hdr_value_t		*val;
420
421	if (error != NULL)
422		*error = 0;
423
424	if (msg == NULL)  {
425		if (error != NULL)
426			*error = EINVAL;
427		return (NULL);
428	}
429	header = sip_get_header(msg, SIP_CSEQ, NULL, error);
430	if (header == NULL) {
431		if (error != NULL)
432			*error = EINVAL;
433		return (NULL);
434	}
435	val = (sip_hdr_value_t *)sip_get_header_value(header, error);
436	if (val == NULL) {
437		if (error != NULL)
438			*error = EPROTO;
439		return (NULL);
440	}
441	if (error != NULL && val->sip_value.value_state == SIP_VALUE_BAD)
442		*error = EPROTO;
443
444	switch (type) {
445		case SIP_CSEQ_NUM:
446			return (&(val->cseq_num));
447		case SIP_CSEQ_METHOD:
448			return (&(val->cseq_method));
449	}
450	if (error != NULL)
451		*error = EINVAL;
452	return (NULL);
453}
454
455/*
456 * Get CSEQ number
457 */
458int
459sip_get_callseq_num(sip_msg_t sip_msg, int *error)
460{
461	int	*r;
462
463	r = (int *)sip_get_cseq_val(sip_msg, SIP_CSEQ_NUM, error);
464	return (r == NULL ? -1 : *r);
465}
466
467/*
468 * Get CSEQ method
469 */
470sip_method_t
471sip_get_callseq_method(sip_msg_t sip_msg, int *error)
472{
473	sip_method_t	*r;
474
475	r = (sip_method_t *)sip_get_cseq_val(sip_msg, SIP_CSEQ_METHOD, error);
476	return (r == NULL ? -1 : *r);
477}
478
479/*
480 * Via header can have more than one value
481 * so we require a value to be passed in.
482 */
483const sip_str_t *
484sip_get_via_sent_by_host(sip_header_value_t value, int *error)
485{
486	sip_hdr_value_t	*via_value;
487
488	if (error != NULL)
489		*error = 0;
490	if (value == NULL || value->value_state == SIP_VALUE_DELETED) {
491		if (error != NULL)
492			*error = EINVAL;
493		return (NULL);
494	}
495	via_value = (sip_hdr_value_t *)value;
496	if (via_value->sip_value_state == SIP_VALUE_BAD && error != NULL)
497		*error = EPROTO;
498	return (&via_value->via_sent_by_host);
499}
500
501/*
502 * Via header can have more than one value
503 * so we require a value to be passed in.
504 */
505int
506sip_get_via_sent_by_port(sip_header_value_t value, int *error)
507{
508	sip_hdr_value_t	*via_value;
509
510	if (error != NULL)
511		*error = 0;
512	if (value == NULL || value->value_state == SIP_VALUE_DELETED) {
513		if (error != NULL)
514			*error = EINVAL;
515		return (-1);
516	}
517	via_value = (sip_hdr_value_t *)value;
518	if (via_value->sip_value_state == SIP_VALUE_BAD && error != NULL)
519		*error = EPROTO;
520	return (via_value->via_sent_by_port);
521}
522
523/*
524 * Return the protocol version from the VIA value
525 */
526const sip_str_t *
527sip_get_via_sent_protocol_version(sip_header_value_t value, int *error)
528{
529	sip_hdr_value_t *via_value;
530
531	if (value == NULL || value->value_state == SIP_VALUE_DELETED) {
532		if (error != NULL)
533			*error = EINVAL;
534		return (NULL);
535	}
536	via_value = (sip_hdr_value_t *)value;
537	if (via_value->sip_value_state == SIP_VALUE_BAD && error != NULL)
538		*error = EPROTO;
539	return (&via_value->via_protocol_vers);
540}
541
542/*
543 * Return the protocol name
544 */
545const sip_str_t *
546sip_get_via_sent_protocol_name(sip_header_value_t value, int *error)
547{
548	sip_hdr_value_t	*via_value;
549
550	if (error != NULL)
551		*error = 0;
552	if (value == NULL || value->value_state == SIP_VALUE_DELETED) {
553		if (error != NULL)
554			*error = EINVAL;
555		return (NULL);
556	}
557	via_value = (sip_hdr_value_t *)value;
558	if (via_value->sip_value_state == SIP_VALUE_BAD && error != NULL)
559		*error = EPROTO;
560	return (&via_value->via_protocol_name);
561}
562
563/*
564 * Return the transport from the VIA value
565 */
566const sip_str_t *
567sip_get_via_sent_transport(sip_header_value_t value, int *error)
568{
569	sip_hdr_value_t	*via_value;
570
571	if (error != NULL)
572		*error = 0;
573	if (value == NULL || value->value_state == SIP_VALUE_DELETED) {
574		if (error != NULL)
575			*error = EINVAL;
576		return (NULL);
577	}
578	via_value = (sip_hdr_value_t *)value;
579	if (via_value->sip_value_state == SIP_VALUE_BAD && error != NULL)
580		*error = EPROTO;
581	return (&via_value->via_protocol_transport);
582}
583
584/*
585 * get the branch id from the topmost VIA header
586 */
587char *
588sip_get_branchid(sip_msg_t sip_msg, int *error)
589{
590	_sip_header_t		*header;
591	sip_parsed_header_t	*parsed_header;
592	sip_hdr_value_t		*via_value;
593	const sip_str_t		*param_value;
594	char			*bid;
595	_sip_msg_t		*_sip_msg;
596
597	if (error != NULL)
598		*error = 0;
599
600	if (sip_msg == NULL) {
601		if (error != NULL)
602			*error = EINVAL;
603		return (NULL);
604	}
605
606	_sip_msg = (_sip_msg_t *)sip_msg;
607
608	(void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
609	header = sip_search_for_header(_sip_msg, SIP_VIA, NULL);
610	if (header == NULL) {
611		if (error != NULL)
612			*error = EINVAL;
613		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
614		return (NULL);
615	}
616	if (sip_parse_via_header(header, &parsed_header) != 0) {
617		if (error != NULL)
618			*error = EPROTO;
619		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
620		return (NULL);
621	}
622	if (parsed_header == NULL) {
623		if (error != NULL)
624			*error = EPROTO;
625		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
626		return (NULL);
627	}
628	via_value = (sip_hdr_value_t *)parsed_header->value;
629	if (via_value == NULL || via_value->sip_value_state == SIP_VALUE_BAD) {
630		if (error != NULL)
631			*error = EPROTO;
632		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
633		return (NULL);
634	}
635	param_value = sip_get_param_value((sip_header_value_t)via_value,
636	    "branch", error);
637
638	if (param_value == NULL) {
639		if (error != NULL)
640			*error = EINVAL;
641		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
642		return (NULL);
643	}
644
645	bid = (char *)malloc(param_value->sip_str_len + 1);
646	if (bid == NULL) {
647		if (error != NULL)
648			*error = ENOMEM;
649		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
650		return (NULL);
651	}
652	(void) strncpy(bid, param_value->sip_str_ptr,
653	    param_value->sip_str_len);
654	bid[param_value->sip_str_len] = '\0';
655	(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
656	return (bid);
657}
658
659/*
660 * adds branchid to the topmost VIA header, if a branchid already exists,
661 * returns error.
662 */
663int
664sip_add_branchid_to_via(sip_msg_t sip_msg, char *branchid)
665{
666	int		err = 0;
667	char		*param;
668	int		plen;
669	sip_header_t	via_hdr;
670	_sip_msg_t	*_sip_msg;
671
672	if (sip_msg == NULL)
673		return (EINVAL);
674	/*
675	 * If there is already a branchid param, error?
676	 */
677	if (sip_get_branchid(sip_msg, NULL) != NULL)
678		return (EINVAL);
679	_sip_msg = (_sip_msg_t *)sip_msg;
680	(void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
681	via_hdr = (sip_header_t)sip_search_for_header(_sip_msg, SIP_VIA, NULL);
682	(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
683	if (via_hdr == NULL)
684		return (EINVAL);
685	plen = strlen(branchid) + strlen("branch=") + 1;
686	param = malloc(plen);
687	if (param == NULL)
688		return (ENOMEM);
689	(void) snprintf(param, plen, "branch=%s", branchid);
690
691	(void) sip_add_param(via_hdr, param, &err);
692	free(param);
693
694	return (err);
695}
696
697/*
698 * returns the number of VIA headers in the SIP message
699 */
700int
701sip_get_num_via(sip_msg_t sip_msg, int *error)
702{
703	_sip_msg_t	*_sip_msg;
704	sip_header_t	hdr;
705	int		via_cnt = 0;
706
707	if (error != NULL)
708		*error = 0;
709	if (sip_msg == NULL) {
710		if (error != NULL)
711			*error = EINVAL;
712		return (via_cnt);
713	}
714	_sip_msg = (_sip_msg_t *)sip_msg;
715	(void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
716	hdr = (sip_header_t)sip_search_for_header(_sip_msg, SIP_VIA, NULL);
717	while (hdr != NULL) {
718		via_cnt++;
719		hdr = (sip_header_t)sip_search_for_header(_sip_msg, SIP_VIA,
720		    hdr);
721	}
722	(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
723	return (via_cnt);
724}
725
726/*
727 * Return Max-Forward value
728 */
729int
730sip_get_maxforward(sip_msg_t sip_msg, int *error)
731{
732	int	*r;
733
734	r = (int *)sip_get_val_from_msg(sip_msg, SIP_MAX_FORWARDS, SIP_INT_VAL,
735	    B_FALSE, B_FALSE, error);
736	if (r == NULL)
737		return (-1);
738	return (*r);
739}
740
741/*
742 * Get the content type
743 */
744const sip_str_t *
745sip_get_content_type(sip_msg_t sip_msg, int *error)
746{
747	sip_str_t	*r;
748
749	r = (sip_str_t *)sip_get_val_from_msg(sip_msg, SIP_CONTENT_TYPE,
750	    SIP_STRS_VAL, B_TRUE, B_FALSE, error);
751	return (r);
752}
753
754/*
755 * Get the content sub-type
756 */
757const sip_str_t *
758sip_get_content_sub_type(sip_msg_t sip_msg, int *error)
759{
760	sip_str_t	*r;
761
762	r = (sip_str_t *)sip_get_val_from_msg(sip_msg, SIP_CONTENT_TYPE,
763	    SIP_STRS_VAL, B_FALSE, B_FALSE, error);
764	return (r);
765}
766
767/*
768 * Return the content-length value
769 */
770int
771sip_get_content_length(sip_msg_t sip_msg, int *error)
772{
773	int	*r;
774
775	r = (int *)sip_get_val_from_msg(sip_msg, SIP_CONTENT_LENGTH,
776	    SIP_INT_VAL, B_FALSE, B_FALSE, error);
777	if (r == NULL)
778		return (-1);
779	return (*r);
780}
781
782/*
783 * get allow-events
784 */
785const sip_str_t *
786sip_get_allow_events(sip_header_value_t value, int *error)
787{
788	sip_str_t	*r;
789	sip_hdr_value_t	*val = (sip_hdr_value_t *)value;
790
791	r = (sip_str_t *)sip_get_val_from_hdr(val, SIP_STR_VAL, B_TRUE, error);
792	return (r);
793}
794
795/*
796 * get event
797 */
798const sip_str_t *
799sip_get_event(sip_msg_t sip_msg, int *error)
800{
801	sip_str_t	*r;
802
803	r = (sip_str_t *)sip_get_val_from_msg(sip_msg, SIP_EVENT, SIP_STR_VAL,
804	    B_FALSE, B_FALSE, error);
805	return (r);
806}
807
808/*
809 * get subscription state
810 */
811const sip_str_t *
812sip_get_substate(sip_msg_t sip_msg, int *error)
813{
814	sip_str_t	*r;
815
816	r = (sip_str_t *)sip_get_val_from_msg(sip_msg, SIP_SUBSCRIPTION_STATE,
817	    SIP_STR_VAL, B_FALSE, B_FALSE, error);
818	return (r);
819}
820
821/*
822 * get accept type
823 */
824const sip_str_t *
825sip_get_accept_type(sip_header_value_t value, int *error)
826{
827	sip_str_t	*r;
828	sip_hdr_value_t	*val = (sip_hdr_value_t *)value;
829
830	r = (sip_str_t *)sip_get_val_from_hdr(val, SIP_STRS_VAL, B_TRUE, error);
831	return (r);
832}
833
834/*
835 * get accept subtype
836 */
837const sip_str_t *
838sip_get_accept_sub_type(sip_header_value_t value, int *error)
839{
840	sip_str_t	*r;
841	sip_hdr_value_t	*val = (sip_hdr_value_t *)value;
842
843	r = (sip_str_t *)sip_get_val_from_hdr(val, SIP_STRS_VAL, B_FALSE,
844	    error);
845	return (r);
846}
847
848/*
849 * accept-encode can have more than one value
850 */
851const sip_str_t *
852sip_get_accept_enc(sip_header_value_t value, int *error)
853{
854	sip_str_t	*r;
855	sip_hdr_value_t	*val = (sip_hdr_value_t *)value;
856
857	r = (sip_str_t *)sip_get_val_from_hdr(val, SIP_STR_VAL, B_FALSE, error);
858	return (r);
859}
860
861/*
862 * accept-language can have more than one value
863 */
864const sip_str_t *
865sip_get_accept_lang(sip_header_value_t value, int *error)
866{
867	sip_str_t	*r;
868	sip_hdr_value_t	*val = (sip_hdr_value_t *)value;
869
870	r = (sip_str_t *)sip_get_val_from_hdr(val, SIP_STR_VAL, B_FALSE, error);
871	return (r);
872}
873
874/*
875 * get URI from the alert-info header
876 */
877const sip_str_t *
878sip_get_alert_info_uri(sip_header_value_t value, int *error)
879{
880	sip_str_t	*r;
881	sip_hdr_value_t	*val = (sip_hdr_value_t *)value;
882
883	r = (sip_str_t *)sip_get_val_from_hdr(val, SIP_STR_VAL, B_FALSE, error);
884	return (r);
885}
886
887/*
888 * get method from allow header
889 */
890sip_method_t
891sip_get_allow_method(sip_header_value_t value, int *error)
892{
893	int		*r;
894	sip_hdr_value_t	*val = (sip_hdr_value_t *)value;
895
896	r = (int *)sip_get_val_from_hdr(val, SIP_INT_VAL, B_FALSE, error);
897	return (r == NULL ? -1 : (sip_method_t)*r);
898}
899
900/*
901 * get URI from call-info header
902 */
903const sip_str_t *
904sip_get_call_info_uri(sip_header_value_t value, int *error)
905{
906	sip_str_t	*r;
907	sip_hdr_value_t	*val = (sip_hdr_value_t *)value;
908
909	r = (sip_str_t *)sip_get_val_from_hdr(val, SIP_STR_VAL, B_FALSE, error);
910	return (r);
911}
912
913/*
914 * get content-disposition value
915 */
916const sip_str_t *
917sip_get_content_disp(sip_msg_t sip_msg, int *error)
918{
919	sip_str_t	*r;
920
921	r = (sip_str_t *)sip_get_val_from_msg(sip_msg, SIP_CONTENT_DIS,
922	    SIP_STR_VAL, B_FALSE, B_FALSE, error);
923	return (r);
924}
925
926/*
927 * get content-encoding value
928 */
929const sip_str_t *
930sip_get_content_enc(sip_header_value_t value, int *error)
931{
932	sip_str_t	*r;
933	sip_hdr_value_t	*val = (sip_hdr_value_t *)value;
934
935	r = (sip_str_t *)sip_get_val_from_hdr(val, SIP_STR_VAL, B_FALSE, error);
936	return (r);
937}
938
939/*
940 * get content-language value
941 */
942const sip_str_t *
943sip_get_content_lang(sip_header_value_t value, int *error)
944{
945	sip_str_t	*r;
946	sip_hdr_value_t	*val = (sip_hdr_value_t *)value;
947
948	r = (sip_str_t *)sip_get_val_from_hdr(val, SIP_STR_VAL, B_FALSE, error);
949	return (r);
950}
951
952/*
953 * sip_get_date_time, day, wkday, month, year
954 */
955#define	D_TIME		0x01
956#define	D_DAY		0x02
957#define	D_MONTH		0x03
958#define	D_YEAR		0x04
959#define	D_WKDAY		0x05
960#define	D_TIMEZONE	0x06
961
962/*
963 * get date information
964 */
965static void *
966sip_get_date_val(sip_msg_t msg, int type, int *error)
967{
968	const _sip_header_t	*header;
969	sip_hdr_value_t		*val;
970
971	if (error != NULL)
972		*error = 0;
973	if (msg == NULL) {
974		if (error != NULL)
975			*error = EINVAL;
976		return (NULL);
977	}
978	header = sip_get_header(msg, SIP_DATE, NULL, error);
979	if (header == NULL) {
980		if (error != NULL)
981			*error = EINVAL;
982		return (NULL);
983	}
984
985	val = (sip_hdr_value_t *)sip_get_header_value(header, error);
986	if (val == NULL) {
987		if (error != NULL)
988			*error = EPROTO;
989		return (NULL);
990	}
991	if (error != NULL && val->sip_value.value_state == SIP_VALUE_BAD)
992		*error = EPROTO;
993	switch (type) {
994		case (D_TIME):
995			return (&(val->date_t));
996		case (D_DAY):
997			return (&(val->date_d));
998		case (D_MONTH):
999			return (&(val->date_m));
1000		case (D_YEAR):
1001			return (&(val->date_y));
1002		case (D_WKDAY):
1003			return (&(val->date_wd));
1004		case (D_TIMEZONE):
1005			return (&(val->date_tz));
1006	}
1007	if (error != NULL)
1008		*error = EINVAL;
1009	return (NULL);
1010}
1011
1012/*
1013 * get time value
1014 */
1015const sip_str_t *
1016sip_get_date_time(sip_msg_t sip_msg, int *error)
1017{
1018	sip_str_t	*r;
1019
1020	r = (sip_str_t *)sip_get_date_val(sip_msg, D_TIME, error);
1021	return (r);
1022}
1023
1024/*
1025 * get day
1026 */
1027int
1028sip_get_date_day(sip_msg_t sip_msg, int *error)
1029{
1030	int	*r = NULL;
1031
1032	r = sip_get_date_val(sip_msg, D_DAY, error);
1033	return (r == NULL ? -1 : *(int *)r);
1034}
1035
1036/*
1037 * get month
1038 */
1039const sip_str_t *
1040sip_get_date_month(sip_msg_t sip_msg, int *error)
1041{
1042	sip_str_t	*r;
1043
1044	r = (sip_str_t *)sip_get_date_val(sip_msg, D_MONTH, error);
1045	return (r);
1046}
1047
1048/*
1049 * get year
1050 */
1051int
1052sip_get_date_year(sip_msg_t sip_msg, int *error)
1053{
1054	int	*r;
1055
1056	r = (int *)sip_get_date_val(sip_msg, D_YEAR, error);
1057	return (r == NULL ? -1 : *r);
1058}
1059
1060/*
1061 * get day of the week
1062 */
1063const sip_str_t *
1064sip_get_date_wkday(sip_msg_t sip_msg, int *error)
1065{
1066	sip_str_t	*r;
1067
1068	r = (sip_str_t *)sip_get_date_val(sip_msg, D_WKDAY, error);
1069	return (r);
1070}
1071
1072/*
1073 * get the timezone
1074 */
1075const sip_str_t *
1076sip_get_date_timezone(sip_msg_t sip_msg, int *error)
1077{
1078	sip_str_t	*r;
1079
1080	r = (sip_str_t *)sip_get_date_val(sip_msg, D_TIMEZONE, error);
1081	return (r);
1082}
1083
1084/*
1085 * get error-info URI
1086 */
1087const sip_str_t *
1088sip_get_error_info_uri(sip_header_value_t value, int *error)
1089{
1090	sip_str_t	*r;
1091	sip_hdr_value_t	*val = (sip_hdr_value_t *)value;
1092
1093	r = (sip_str_t *)sip_get_val_from_hdr(val, SIP_STR_VAL, B_FALSE, error);
1094	return (r);
1095}
1096
1097/*
1098 * get priv-value from privacy
1099 */
1100const sip_str_t *
1101sip_get_priv_value(sip_header_value_t value, int *error)
1102{
1103	sip_str_t	*r;
1104	sip_hdr_value_t	*val = (sip_hdr_value_t *)value;
1105
1106	r = (sip_str_t *)sip_get_val_from_hdr(val, SIP_STR_VAL, B_FALSE, error);
1107	return (r);
1108}
1109
1110/*
1111 * return expires value
1112 */
1113int
1114sip_get_expires(sip_msg_t sip_msg, int *error)
1115{
1116	int	*r;
1117
1118	r = (int *)sip_get_val_from_msg(sip_msg, SIP_EXPIRE, SIP_INT_VAL,
1119	    B_FALSE, B_FALSE, error);
1120	if (r == NULL)
1121		return (-1);
1122	return (*r);
1123}
1124
1125/*
1126 * get reply-to value
1127 */
1128const sip_str_t *
1129sip_get_in_reply_to(sip_header_value_t value, int *error)
1130{
1131	sip_str_t	*r;
1132	sip_hdr_value_t	*val = (sip_hdr_value_t *)value;
1133
1134	r = (sip_str_t *)sip_get_val_from_hdr(val, SIP_STR_VAL, B_FALSE, error);
1135	return (r);
1136}
1137
1138/*
1139 * get min-expires value
1140 */
1141int
1142sip_get_min_expires(sip_msg_t sip_msg, int *error)
1143{
1144	int	*r;
1145
1146	r = (int *)sip_get_val_from_msg(sip_msg, SIP_MIN_EXPIRE, SIP_INT_VAL,
1147	    B_FALSE, B_FALSE, error);
1148	if (r == NULL)
1149		return (-1);
1150	return (*r);
1151}
1152
1153/*
1154 * get mime-version
1155 */
1156const sip_str_t *
1157sip_get_mime_version(sip_msg_t sip_msg, int *error)
1158{
1159	sip_str_t	*r;
1160
1161	r = (sip_str_t *)sip_get_val_from_msg(sip_msg, SIP_MIME_VERSION,
1162	    SIP_STR_VAL, B_FALSE, B_FALSE, error);
1163	return (r);
1164}
1165
1166/*
1167 * get organization value
1168 */
1169const sip_str_t *
1170sip_get_org(sip_msg_t sip_msg, int *error)
1171{
1172	sip_str_t	*r;
1173
1174	r = (sip_str_t *)sip_get_val_from_msg(sip_msg, SIP_ORGANIZATION,
1175	    SIP_STR_VAL, B_FALSE, B_TRUE, error);
1176	return (r);
1177}
1178
1179/*
1180 * get priority value
1181 */
1182const sip_str_t *
1183sip_get_priority(sip_msg_t sip_msg, int *error)
1184{
1185	sip_str_t	*r;
1186
1187	r = (sip_str_t *)sip_get_val_from_msg(sip_msg, SIP_PRIORITY,
1188	    SIP_STR_VAL, B_FALSE, B_FALSE, error);
1189	return (r);
1190}
1191
1192/*
1193 * get display name
1194 */
1195const sip_str_t *
1196sip_get_pidentity_display_name(sip_header_value_t value, int *error)
1197{
1198	sip_str_t	*r;
1199	sip_hdr_value_t	*val = (sip_hdr_value_t *)value;
1200
1201	r = (sip_str_t *)sip_get_val_from_hdr(val, SIP_STRS_VAL, B_TRUE, error);
1202
1203	return (r);
1204}
1205
1206/*
1207 * get URI
1208 */
1209const sip_str_t *
1210sip_get_pidenty_uri_str(sip_header_value_t value, int *error)
1211{
1212	sip_str_t	*r;
1213	sip_hdr_value_t	*val = (sip_hdr_value_t *)value;
1214
1215	r = (sip_str_t *)sip_get_val_from_hdr(val, SIP_STRS_VAL, B_FALSE,
1216	    error);
1217
1218	return (r);
1219}
1220
1221/*
1222 * get display name from passerted-identity header
1223 */
1224const sip_str_t *
1225sip_get_passertedid_display_name(sip_header_value_t value, int *error)
1226{
1227	return (sip_get_pidentity_display_name(value, error));
1228}
1229
1230/*
1231 * get URI from passerted-identity header
1232 */
1233const sip_str_t *
1234sip_get_passertedid_uri_str(sip_header_value_t value, int *error)
1235{
1236	return (sip_get_pidenty_uri_str(value, error));
1237}
1238
1239/*
1240 * get display name from ppreferred-identity header
1241 */
1242const sip_str_t *
1243sip_get_ppreferredid_display_name(sip_header_value_t value, int *error)
1244{
1245	return (sip_get_pidentity_display_name(value, error));
1246}
1247
1248/*
1249 * get URI from ppreferred-identity header
1250 */
1251const sip_str_t *
1252sip_get_ppreferredid_uri_str(sip_header_value_t value, int *error)
1253{
1254	return (sip_get_pidenty_uri_str(value, error));
1255}
1256
1257#define	SIP_RACK_RESP_NUM	1
1258#define	SIP_RACK_CSEQ_NUM	2
1259#define	SIP_RACK_METHOD		3
1260
1261/*
1262 * Get rack information
1263 */
1264static void *
1265sip_get_rack_val(sip_msg_t msg, int type, int *error)
1266{
1267	const _sip_header_t	*header;
1268	sip_hdr_value_t		*val;
1269
1270	if (error != NULL)
1271		*error = 0;
1272
1273	if (msg == NULL)  {
1274		if (error != NULL)
1275			*error = EINVAL;
1276		return (NULL);
1277	}
1278	header = sip_get_header(msg, SIP_RACK, NULL, error);
1279	if (header == NULL) {
1280		if (error != NULL)
1281			*error = EINVAL;
1282		return (NULL);
1283	}
1284	val = (sip_hdr_value_t *)sip_get_header_value(header, error);
1285	if (val == NULL) {
1286		if (error != NULL)
1287			*error = EPROTO;
1288		return (NULL);
1289	}
1290	if (error != NULL && val->sip_value.value_state == SIP_VALUE_BAD)
1291		*error = EPROTO;
1292
1293	switch (type) {
1294		case SIP_RACK_RESP_NUM:
1295			return (&(val->rack_resp));
1296		case SIP_RACK_CSEQ_NUM:
1297			return (&(val->rack_cseq));
1298		case SIP_RACK_METHOD:
1299			return (&(val->rack_method));
1300	}
1301	if (error != NULL)
1302		*error = EINVAL;
1303	return (NULL);
1304}
1305
1306/*
1307 * get response number for rack
1308 */
1309int
1310sip_get_rack_resp_num(sip_msg_t sip_msg, int *error)
1311{
1312	int	*r;
1313
1314	r = (int *)sip_get_rack_val(sip_msg, SIP_RACK_RESP_NUM, error);
1315
1316	return (r == NULL ? -1 : *r);
1317}
1318
1319/*
1320 * get sequence number for rack
1321 */
1322int
1323sip_get_rack_cseq_num(sip_msg_t sip_msg, int *error)
1324{
1325	int	*r;
1326
1327	r = (int *)sip_get_rack_val(sip_msg, SIP_RACK_CSEQ_NUM, error);
1328
1329	return (r == NULL ? -1 : *r);
1330}
1331
1332/*
1333 * get method for rack
1334 */
1335sip_method_t
1336sip_get_rack_method(sip_msg_t sip_msg, int *error)
1337{
1338	sip_method_t	*r;
1339
1340	r = (sip_method_t *)sip_get_rack_val(sip_msg, SIP_RACK_METHOD, error);
1341
1342	return (r == NULL ? -1 : *r);
1343}
1344
1345/*
1346 * get response number from rseq
1347 */
1348int
1349sip_get_rseq_resp_num(sip_msg_t sip_msg, int *error)
1350{
1351	int	*r;
1352
1353	r = (int *)sip_get_val_from_msg(sip_msg, SIP_RSEQ, SIP_INT_VAL,
1354	    B_FALSE, B_FALSE, error);
1355
1356	return (r == NULL ? -1 : *r);
1357}
1358
1359/*
1360 * get reply-to display name
1361 */
1362const sip_str_t *
1363sip_get_replyto_display_name(sip_msg_t sip_msg, int *error)
1364{
1365	sip_str_t	*r;
1366
1367	r = (sip_str_t *)sip_get_val_from_msg(sip_msg, SIP_REPLYTO,
1368	    SIP_STRS_VAL, B_TRUE, B_FALSE, error);
1369	return (r);
1370}
1371
1372/*
1373 * get reply-to URI
1374 */
1375const sip_str_t *
1376sip_get_replyto_uri_str(sip_msg_t sip_msg, int *error)
1377{
1378	sip_str_t	*r;
1379
1380	r = (sip_str_t *)sip_get_val_from_msg(sip_msg, SIP_REPLYTO,
1381	    SIP_STRS_VAL, B_FALSE, B_FALSE, error);
1382
1383	return (r);
1384}
1385
1386/*
1387 * get require value
1388 */
1389const sip_str_t *
1390sip_get_require(sip_header_value_t value, int *error)
1391{
1392	sip_str_t	*r;
1393	sip_hdr_value_t	*val = (sip_hdr_value_t *)value;
1394
1395	r = (sip_str_t *)sip_get_val_from_hdr(val, SIP_STR_VAL, B_FALSE, error);
1396	return (r);
1397}
1398
1399/*
1400 * get retry-after time
1401 */
1402int
1403sip_get_retry_after_time(sip_msg_t sip_msg, int *error)
1404{
1405	int	*t;
1406
1407	t = (int *)sip_get_val_from_msg(sip_msg, SIP_RETRY_AFTER,
1408	    SIP_INTSTR_VAL, B_FALSE, B_FALSE, error);
1409	if (t == NULL)
1410		return (-1);
1411	return (*t);
1412}
1413
1414/*
1415 * get retry-after comments
1416 */
1417const sip_str_t *
1418sip_get_retry_after_cmts(sip_msg_t sip_msg, int *error)
1419{
1420	sip_str_t	*r;
1421
1422	r = (sip_str_t *)sip_get_val_from_msg(sip_msg, SIP_RETRY_AFTER,
1423	    SIP_INTSTR_VAL, B_TRUE, B_FALSE, error);
1424	return (r);
1425}
1426
1427/*
1428 * get subject
1429 */
1430const sip_str_t *
1431sip_get_subject(sip_msg_t sip_msg, int *error)
1432{
1433	sip_str_t	*r;
1434
1435	r = (sip_str_t *)sip_get_val_from_msg(sip_msg, SIP_SUBJECT, SIP_STR_VAL,
1436	    B_FALSE, B_TRUE, error);
1437	return (r);
1438}
1439
1440/*
1441 * get supported
1442 */
1443const sip_str_t *
1444sip_get_supported(sip_header_value_t value, int *error)
1445{
1446	sip_str_t	*r;
1447	sip_hdr_value_t	*val = (sip_hdr_value_t *)value;
1448
1449	r = (sip_str_t *)sip_get_val_from_hdr(val, SIP_STR_VAL, B_FALSE, error);
1450	return (r);
1451}
1452
1453/*
1454 * get timestamp delay
1455 */
1456const sip_str_t *
1457sip_get_tstamp_delay(sip_msg_t sip_msg, int *error)
1458{
1459	sip_str_t	*t;
1460
1461	t = sip_get_val_from_msg(sip_msg, SIP_TIMESTAMP, SIP_STRS_VAL, B_FALSE,
1462	    B_FALSE, error);
1463	return (t);
1464}
1465
1466/*
1467 * get timestamp
1468 */
1469const sip_str_t *
1470sip_get_tstamp_value(sip_msg_t sip_msg, int *error)
1471{
1472	sip_str_t	*t;
1473
1474	t = sip_get_val_from_msg(sip_msg, SIP_TIMESTAMP, SIP_STRS_VAL, B_TRUE,
1475	    B_FALSE, error);
1476	return (t);
1477}
1478
1479/*
1480 * get unsupported value
1481 */
1482const sip_str_t *
1483sip_get_unsupported(sip_header_value_t value, int *error)
1484{
1485	sip_str_t	*r;
1486	sip_hdr_value_t	*val = (sip_hdr_value_t *)value;
1487
1488	r = (sip_str_t *)sip_get_val_from_hdr(val, SIP_STR_VAL, B_FALSE, error);
1489	return (r);
1490}
1491
1492/*
1493 * get server value from message
1494 */
1495const sip_str_t *
1496sip_get_server(sip_msg_t sip_msg, int *error)
1497{
1498	sip_str_t	*r;
1499
1500	r = (sip_str_t *)sip_get_val_from_msg(sip_msg, SIP_SERVER, SIP_STR_VAL,
1501	    B_FALSE, B_FALSE, error);
1502	return (r);
1503}
1504
1505/*
1506 * get user-agent value
1507 */
1508const sip_str_t *
1509sip_get_user_agent(sip_msg_t sip_msg, int *error)
1510{
1511	sip_str_t	*r;
1512
1513	r = sip_get_val_from_msg(sip_msg, SIP_USER_AGENT, SIP_STR_VAL, B_FALSE,
1514	    B_FALSE, error);
1515	return (r);
1516}
1517
1518#define	W_CODE	0x05
1519#define	W_AGENT	0x06
1520#define	W_TEXT	0x07
1521
1522/*
1523 * get warning info
1524 */
1525static void *
1526sip_get_warninfo(sip_header_value_t value, int info, int *error)
1527{
1528	sip_hdr_value_t	*val = (sip_hdr_value_t *)value;
1529
1530	if (error != NULL)
1531		*error = 0;
1532
1533	if (val == NULL) {
1534		if (error != NULL)
1535			*error = EINVAL;
1536		return (NULL);
1537	}
1538
1539	if (val->sip_value_state == SIP_VALUE_BAD) {
1540		*error = EPROTO;
1541		return (NULL);
1542	}
1543
1544	switch (info) {
1545		case (W_CODE):
1546			return (&(val->warn_code));
1547		case (W_AGENT):
1548			return (&(val->warn_agt));
1549		case (W_TEXT):
1550			return (&(val->warn_text));
1551	}
1552	if (error != NULL)
1553		*error = EINVAL;
1554	return (NULL);
1555}
1556
1557/*
1558 * get warning code
1559 */
1560int
1561sip_get_warning_code(sip_header_value_t value, int *error)
1562{
1563	int	*c;
1564
1565	if (error != NULL)
1566		*error = 0;
1567
1568	if (value == NULL || value->value_state == SIP_VALUE_DELETED) {
1569		if (error != NULL)
1570			*error = EINVAL;
1571		return (-1);
1572	}
1573	c = (int *)sip_get_warninfo(value, W_CODE, error);
1574	if (c == NULL)
1575		return (-1);
1576	return (*c);
1577}
1578
1579/*
1580 * get warning agent
1581 */
1582const sip_str_t *
1583sip_get_warning_agent(sip_header_value_t value, int *error)
1584{
1585	sip_str_t	*r;
1586
1587	if (value == NULL || value->value_state == SIP_VALUE_DELETED) {
1588		if (error != NULL)
1589			*error = EINVAL;
1590		return (NULL);
1591	}
1592	r = (sip_str_t *)sip_get_warninfo(value, W_AGENT, error);
1593	return (r);
1594}
1595
1596/*
1597 * get warning text
1598 */
1599const sip_str_t *
1600sip_get_warning_text(sip_header_value_t value, int *error)
1601{
1602	sip_str_t	*r;
1603
1604	if (value == NULL || value->value_state == SIP_VALUE_DELETED) {
1605		if (error != NULL)
1606			*error = EINVAL;
1607		return (NULL);
1608	}
1609	r = (sip_str_t *)sip_get_warninfo(value, W_TEXT, error);
1610	return (r);
1611}
1612
1613/*
1614 * get authorization scheme
1615 */
1616const sip_str_t *
1617sip_get_author_scheme(sip_msg_t sip_msg, int *error)
1618{
1619	sip_str_t	*r;
1620
1621	r = sip_get_val_from_msg(sip_msg, SIP_AUTHOR, SIP_AUTH_VAL, B_FALSE,
1622	    B_FALSE, error);
1623	return (r);
1624}
1625
1626/*
1627 * get authentication parameter
1628 */
1629static const sip_str_t *
1630sip_get_auth_param(sip_msg_t msg, char *hdr_name, char *pname, int *error)
1631{
1632	const _sip_header_t	*header;
1633	sip_hdr_value_t		*value;
1634	sip_param_t		*param;
1635
1636	if (error != NULL)
1637		*error = 0;
1638
1639	if (msg == NULL || pname == NULL || hdr_name == NULL) {
1640		if (error != NULL)
1641			*error = EINVAL;
1642		return (NULL);
1643	}
1644
1645	header = sip_get_header(msg, hdr_name, NULL, error);
1646	if (header == NULL) {
1647		if (error != NULL)
1648			*error = EINVAL;
1649		return (NULL);
1650	}
1651
1652	value = (sip_hdr_value_t *)sip_get_header_value(header, error);
1653	if (value == NULL) {
1654		if (error != NULL)
1655			*error = EPROTO;
1656		return (NULL);
1657	}
1658
1659	param = sip_get_param_from_list(value->auth_param, pname);
1660	if (param != NULL)
1661		return (&param->param_value);
1662	return (NULL);
1663}
1664
1665/*
1666 * get authentication parameter
1667 */
1668const sip_str_t *
1669sip_get_author_param(sip_msg_t sip_msg, char *name, int *error)
1670{
1671	const sip_str_t	*r;
1672
1673	r = sip_get_auth_param(sip_msg, SIP_AUTHOR, name, error);
1674	return (r);
1675}
1676
1677/*
1678 * get authentication info
1679 */
1680const sip_str_t *
1681sip_get_authen_info(sip_header_value_t value, int *error)
1682{
1683	sip_str_t	*r;
1684	sip_hdr_value_t	*val = (sip_hdr_value_t *)value;
1685
1686	if (error != NULL)
1687		*error = 0;
1688	if (value == NULL || value->value_state == SIP_VALUE_DELETED) {
1689		if (error != NULL)
1690			*error = EINVAL;
1691		return (NULL);
1692	}
1693	r = sip_get_val_from_hdr(val, SIP_STR_VAL, B_FALSE, error);
1694	return (r);
1695}
1696
1697/*
1698 * get proxy-authentication scheme
1699 */
1700const sip_str_t *
1701sip_get_proxy_authen_scheme(sip_msg_t msg, int *error)
1702{
1703	sip_str_t	*r;
1704
1705	r = sip_get_val_from_msg(msg, SIP_PROXY_AUTHEN, SIP_AUTH_VAL, B_FALSE,
1706	    B_FALSE, error);
1707	return (r);
1708}
1709
1710/*
1711 * get proxy authentication parameter
1712 */
1713const sip_str_t *
1714sip_get_proxy_authen_param(sip_msg_t sip_msg, char *name, int *error)
1715{
1716	const sip_str_t	*r;
1717
1718	r = sip_get_auth_param(sip_msg, SIP_PROXY_AUTHEN, name, error);
1719	return (r);
1720}
1721
1722/*
1723 * get proxy-authorization scheme
1724 */
1725const sip_str_t *
1726sip_get_proxy_author_scheme(sip_msg_t msg, int *error)
1727{
1728	sip_str_t	*r;
1729
1730	r = sip_get_val_from_msg(msg, SIP_PROXY_AUTHOR, SIP_AUTH_VAL, B_FALSE,
1731	    B_FALSE, error);
1732	return (r);
1733}
1734
1735/*
1736 * get proxy-authorization parameter
1737 */
1738const sip_str_t *
1739sip_get_proxy_author_param(sip_msg_t sip_msg, char *name, int *error)
1740{
1741	const sip_str_t	*r;
1742
1743	r = sip_get_auth_param(sip_msg, SIP_PROXY_AUTHOR, name, error);
1744	return (r);
1745}
1746
1747/*
1748 * get proxy-require
1749 */
1750const sip_str_t *
1751sip_get_proxy_require(sip_header_value_t value, int *error)
1752{
1753	sip_str_t	*r;
1754	sip_hdr_value_t	*val = (sip_hdr_value_t *)value;
1755
1756	if (error != NULL)
1757		*error = 0;
1758	if (value == NULL || value->value_state == SIP_VALUE_DELETED) {
1759		if (error != NULL)
1760			*error = EINVAL;
1761		return (NULL);
1762	}
1763	r = sip_get_val_from_hdr(val, SIP_STR_VAL, B_FALSE, error);
1764	return (r);
1765}
1766
1767/*
1768 * get www-authentication scheme
1769 */
1770const sip_str_t *
1771sip_get_www_authen_scheme(sip_msg_t msg, int *error)
1772{
1773	sip_str_t	*r;
1774
1775	r = sip_get_val_from_msg(msg, SIP_WWW_AUTHEN, SIP_AUTH_VAL, B_FALSE,
1776	    B_FALSE, error);
1777	return (r);
1778}
1779
1780/*
1781 * get www-authentication parameter
1782 */
1783const sip_str_t *
1784sip_get_www_authen_param(sip_msg_t sip_msg, char *name, int *error)
1785{
1786	const sip_str_t	*r;
1787
1788	r = sip_get_auth_param(sip_msg, SIP_WWW_AUTHEN, name, error);
1789	return (r);
1790}
1791