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