xref: /illumos-gate/usr/src/lib/libsip/common/sip_hdrs_ui.c (revision f012ee0c3db17469b492c2cf757226f3d7b1ebbc)
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  */
41 static void *
42 sip_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  */
91 static void *
92 sip_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  */
125 const sip_str_t *
126 sip_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  */
150 const sip_str_t *
151 sip_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  */
175 const sip_str_t *
176 sip_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  */
185 const sip_str_t *
186 sip_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  */
195 const sip_str_t *
196 sip_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  */
205 const sip_str_t *
206 sip_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  */
214 const sip_str_t *
215 sip_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  */
252 const sip_str_t *
253 sip_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  */
289 const sip_str_t *
290 sip_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  */
298 const sip_str_t *
299 sip_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  */
307 const sip_str_t *
308 sip_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  */
344 const sip_str_t *
345 sip_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  */
353 const sip_str_t *
354 sip_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  */
362 const sip_str_t *
363 sip_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  */
399 const sip_str_t *
400 sip_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  */
415 static void *
416 sip_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  */
458 int
459 sip_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  */
470 sip_method_t
471 sip_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  */
483 const sip_str_t *
484 sip_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  */
505 int
506 sip_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  */
526 const sip_str_t *
527 sip_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  */
545 const sip_str_t *
546 sip_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  */
566 const sip_str_t *
567 sip_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  */
587 char *
588 sip_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  */
663 int
664 sip_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  */
700 int
701 sip_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  */
729 int
730 sip_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  */
744 const sip_str_t *
745 sip_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  */
757 const sip_str_t *
758 sip_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  */
770 int
771 sip_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  */
785 const sip_str_t *
786 sip_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  */
798 const sip_str_t *
799 sip_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  */
811 const sip_str_t *
812 sip_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  */
824 const sip_str_t *
825 sip_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  */
837 const sip_str_t *
838 sip_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  */
851 const sip_str_t *
852 sip_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  */
864 const sip_str_t *
865 sip_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  */
877 const sip_str_t *
878 sip_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  */
890 sip_method_t
891 sip_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  */
903 const sip_str_t *
904 sip_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  */
916 const sip_str_t *
917 sip_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  */
929 const sip_str_t *
930 sip_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  */
942 const sip_str_t *
943 sip_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  */
965 static void *
966 sip_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  */
1015 const sip_str_t *
1016 sip_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  */
1027 int
1028 sip_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  */
1039 const sip_str_t *
1040 sip_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  */
1051 int
1052 sip_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  */
1063 const sip_str_t *
1064 sip_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  */
1075 const sip_str_t *
1076 sip_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  */
1087 const sip_str_t *
1088 sip_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  */
1100 const sip_str_t *
1101 sip_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  */
1113 int
1114 sip_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  */
1128 const sip_str_t *
1129 sip_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  */
1141 int
1142 sip_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  */
1156 const sip_str_t *
1157 sip_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  */
1169 const sip_str_t *
1170 sip_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  */
1182 const sip_str_t *
1183 sip_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  */
1195 const sip_str_t *
1196 sip_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  */
1209 const sip_str_t *
1210 sip_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  */
1224 const sip_str_t *
1225 sip_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  */
1233 const sip_str_t *
1234 sip_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  */
1242 const sip_str_t *
1243 sip_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  */
1251 const sip_str_t *
1252 sip_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  */
1264 static void *
1265 sip_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  */
1309 int
1310 sip_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  */
1322 int
1323 sip_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  */
1335 sip_method_t
1336 sip_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  */
1348 int
1349 sip_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  */
1362 const sip_str_t *
1363 sip_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  */
1375 const sip_str_t *
1376 sip_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  */
1389 const sip_str_t *
1390 sip_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  */
1402 int
1403 sip_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  */
1417 const sip_str_t *
1418 sip_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  */
1430 const sip_str_t *
1431 sip_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  */
1443 const sip_str_t *
1444 sip_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  */
1456 const sip_str_t *
1457 sip_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  */
1469 const sip_str_t *
1470 sip_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  */
1482 const sip_str_t *
1483 sip_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  */
1495 const sip_str_t *
1496 sip_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  */
1508 const sip_str_t *
1509 sip_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  */
1525 static void *
1526 sip_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  */
1560 int
1561 sip_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  */
1582 const sip_str_t *
1583 sip_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  */
1599 const sip_str_t *
1600 sip_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  */
1616 const sip_str_t *
1617 sip_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  */
1629 static const sip_str_t *
1630 sip_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  */
1668 const sip_str_t *
1669 sip_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  */
1680 const sip_str_t *
1681 sip_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  */
1700 const sip_str_t *
1701 sip_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  */
1713 const sip_str_t *
1714 sip_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  */
1725 const sip_str_t *
1726 sip_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  */
1738 const sip_str_t *
1739 sip_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  */
1750 const sip_str_t *
1751 sip_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  */
1770 const sip_str_t *
1771 sip_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  */
1783 const sip_str_t *
1784 sip_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