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