dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / libsip / common / sip_parse_hdrs.c
blobdef08fc43fab665ab1e57c53c5ff8a8a1360286f
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #include <ctype.h>
28 #include <errno.h>
29 #include <stdlib.h>
30 #include <strings.h>
31 #include <sip.h>
33 #include "sip_msg.h"
34 #include "sip_miscdefs.h"
35 #include "sip_parse_generic.h"
36 #include "sip_parse_uri.h"
40 * Accept = "Accept" HCOLON [ accept-range *(COMMA accept-range) ]
41 * accept-range = media-range *(SEMI accept-param)
42 * media-range = ("* / *" | (m-type SLASH "*") | (m-type SLASH m-subtype))
43 * *(SEMI m-param)
44 * accept-param = ("q" EQUAL qvalue) | generic-param
45 * qvalue = ("0" ["." 0*3DIGIT]) | ("1" ["." 0*3DIGIT])
46 * generic-param = token [ EQUAL gen-value]
47 * gen-value = token | host | quoted-str
49 int
50 sip_parse_acpt_header(_sip_header_t *sip_header, sip_parsed_header_t **header)
52 if (sip_is_empty_hdr(sip_header))
53 return (sip_parse_hdr_empty(sip_header, header));
54 return (sip_parse_hdr_parser1(sip_header, header, SIP_SLASH));
58 * Accept-Encoding = "Accept-Encoding" ":" 1#(codings [ ";" "q" "=" qval])
59 * codings = (content-coding | "*")
60 * content-coding = token
62 int
63 sip_parse_acpt_encode_header(_sip_header_t *sip_header,
64 sip_parsed_header_t **header)
66 return (sip_parse_hdr_parser1(sip_header, header, SIP_NUL));
70 * Accept-Language = "Accept-Language" ":" [ lang * (COMMA lang) ]
71 * lang = lang-range *(SEMI accept-param)
72 * lang-range = ((1*8ALPHA * ("-" 1*8ALPHA)) | "*"
74 int
75 sip_parse_acpt_lang_header(_sip_header_t *sip_header,
76 sip_parsed_header_t **header)
78 if (sip_is_empty_hdr(sip_header))
79 return (sip_parse_hdr_empty(sip_header, header));
80 return (sip_parse_hdr_parser1(sip_header, header, SIP_NUL));
84 * Alert-Info = "Alert-Info" ":" alert-param *(COMMA alert-param)
85 * alert-param = LAQUOT absoluteURI RAQUOT * (SEMI generic-param)
87 int
88 sip_parse_alert_header(_sip_header_t *sip_header, sip_parsed_header_t **header)
90 return (sip_parse_hdr_parser3(sip_header, header, SIP_STR_VAL, B_TRUE));
94 * Allow = "Allow" ":" method-name1[, method-name2..]
96 int
97 sip_parse_allow_header(_sip_header_t *hdr, sip_parsed_header_t **phdr)
99 sip_parsed_header_t *parsed_header;
100 sip_hdr_value_t *value = NULL;
101 sip_hdr_value_t *last_value = NULL;
102 int len;
103 int i;
104 int ret;
105 boolean_t multi_value = B_FALSE;
107 if ((ret = sip_prim_parsers(hdr, phdr)) != 0)
108 return (ret);
110 if (*phdr != NULL)
111 return (0);
113 parsed_header = calloc(1, sizeof (sip_parsed_header_t));
114 if (parsed_header == NULL)
115 return (ENOMEM);
116 parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1;
117 parsed_header->sip_header = hdr;
119 while (hdr->sip_hdr_current < hdr->sip_hdr_end) {
120 value = calloc(1, sizeof (sip_hdr_value_t));
121 if (value == NULL) {
122 sip_free_phdr(parsed_header);
123 return (ENOMEM);
125 if (last_value != NULL)
126 last_value->sip_next_value = value;
127 else
128 parsed_header->value = (sip_value_t *)value;
130 value->sip_value_start = hdr->sip_hdr_current;
131 value->sip_value_header = parsed_header;
133 if (sip_find_separator(hdr, SIP_COMMA, SIP_NUL,
134 SIP_NUL, B_FALSE) == 0) {
135 multi_value = B_TRUE;
138 len = hdr->sip_hdr_current - value->sip_value_start;
139 for (i = 1; i < MAX_SIP_METHODS; i++) {
140 if (strncmp(sip_methods[i].name, value->sip_value_start,
141 len) == 0) {
142 break;
145 if (i >= MAX_SIP_METHODS) {
146 value->int_val = 0;
147 value->sip_value_state = SIP_VALUE_BAD;
148 if (multi_value)
149 goto next_val;
150 else
151 goto end;
153 value->int_val = i;
154 if (!multi_value)
155 goto end;
156 next_val:
157 if (sip_find_token(hdr, SIP_COMMA) != 0)
158 break;
159 value->sip_value_end = hdr->sip_hdr_current - 1;
160 last_value = value;
161 (void) sip_skip_white_space(hdr);
164 end:
165 *phdr = parsed_header;
166 return (0);
171 * Call-Info = "Call-Info" HCOLON info * (COMMA info)
172 * info = LAQUOT absoluteURI RAQUOT * (SEMI info-param)
173 * info-param = ("purpose" EQUAL ("icon" | "info" | "card" | token)) |
174 * generic-param
177 sip_parse_callinfo_header(_sip_header_t *sip_header,
178 sip_parsed_header_t **header)
180 return (sip_parse_hdr_parser3(sip_header, header, SIP_STR_VAL, B_TRUE));
184 * Content-Disposition = "Content-Disposition" HCOLON disp-type *
185 * (SEMI disp-param)
186 * disp-type = "render" | "session" | "icon" | "alert" | disp-ext-token
187 * disp-param = handling-param | generic-param
188 * handling-param = "handling" EQUAL("optional" | "required" | other-handling)
189 * other-handling = token
190 * disp-ext-token = token
194 sip_parse_contentdis_header(_sip_header_t *sip_header,
195 sip_parsed_header_t **header)
197 return (sip_parse_hdr_parser1(sip_header, header, SIP_NUL));
201 * Content-Encoding = ("Content-Encoding" | "e") HCOLON content-coding *
202 * (COMMA content-coding)
205 sip_parse_contentencode_header(_sip_header_t *sip_header,
206 sip_parsed_header_t **header)
208 return (sip_parse_hdr_parser1(sip_header, header, SIP_NUL));
212 * Content-Language = ("Content-Language" | "l") HCOLON lang-tag *
213 * (COMMA lang-tag)
214 * lang-tag = primary-tag *("-" subtag)
215 * prmary-tag = 1*8ALPHA
216 * subtag = 1*8ALPHA
219 sip_parse_contentlang_header(_sip_header_t *sip_header,
220 sip_parsed_header_t **header)
222 return (sip_parse_hdr_parser1(sip_header, header, SIP_NUL));
226 * Date = "Date" HCOLON SIPdate
227 * SIPdate = wkday "," SP date1 SP time SP "GMT"
228 * date1 = 2DIGIT SP mnth SP 4DIGIT; day month year
229 * time = 2DIGIT ":" 2DIGIT ":" 2DIGIT
230 * wkday = "Mon" | "Tue" | "Wed" | "Thu" | "Fri" | "Sat" | "Sun"
231 * month = "Jan" | "Feb" etc
234 sip_parse_date_header(_sip_header_t *sip_header, sip_parsed_header_t **header)
236 sip_parsed_header_t *parsed_header;
237 int r;
238 sip_hdr_value_t *value = NULL;
240 if ((r = sip_prim_parsers(sip_header, header)) != 0)
241 return (r);
243 if (*header != NULL)
244 return (0);
246 parsed_header = calloc(1, sizeof (sip_parsed_header_t));
247 if (parsed_header == NULL)
248 return (ENOMEM);
249 parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1;
250 parsed_header->sip_header = sip_header;
252 value = calloc(1, sizeof (sip_hdr_value_t));
253 if (value == NULL) {
254 sip_free_phdr(parsed_header);
255 return (ENOMEM);
257 parsed_header->value = (sip_value_t *)value;
259 value->sip_value_start = sip_header->sip_hdr_current;
260 value->sip_value_header = parsed_header;
261 value->date_wd_ptr = sip_header->sip_hdr_current;
262 if (sip_find_token(sip_header, SIP_COMMA) == 0) {
263 value->date_wd_len = sip_header->sip_hdr_current -
264 value->date_wd_ptr - 1;
265 sip_header->sip_hdr_current++;
266 if (sip_skip_white_space(sip_header) != 0) {
267 value->sip_value_state = SIP_VALUE_BAD;
268 return (EPROTO);
270 } else {
271 value->sip_value_state = SIP_VALUE_BAD;
272 return (EPROTO);
275 if (sip_skip_white_space(sip_header) != 0) {
276 value->sip_value_state = SIP_VALUE_BAD;
277 return (EPROTO);
279 r = sip_atoi(sip_header, &value->date_d);
280 if (r != 0 || value->date_d < 0 || value->date_d > 31) {
281 value->sip_value_state = SIP_VALUE_BAD;
282 return (EPROTO);
284 if (sip_skip_white_space(sip_header) != 0) {
285 value->sip_value_state = SIP_VALUE_BAD;
286 return (EPROTO);
288 value->date_m_ptr = sip_header->sip_hdr_current;
289 if (sip_find_token(sip_header, SIP_SP) == 0) {
290 value->date_m_len = sip_header->sip_hdr_current -
291 value->date_m_ptr - 1;
292 } else {
293 value->sip_value_state = SIP_VALUE_BAD;
294 return (EPROTO);
297 r = sip_atoi(sip_header, &value->date_y);
298 if (r != 0 || value->date_y < 0) {
299 value->sip_value_state = SIP_VALUE_BAD;
300 return (EPROTO);
302 if (sip_skip_white_space(sip_header) != 0) {
303 value->sip_value_state = SIP_VALUE_BAD;
304 return (EPROTO);
306 value->date_t_ptr = sip_header->sip_hdr_current;
307 if (sip_find_token(sip_header, SIP_SP) == 0) {
308 value->date_t_len = sip_header->sip_hdr_current -
309 value->date_t_ptr - 1;
310 } else {
311 value->sip_value_state = SIP_VALUE_BAD;
312 return (EPROTO);
315 value->date_tz_ptr = sip_header->sip_hdr_current;
317 * minus 2 to get rid of the CRLF
319 value->date_tz_len = sip_header->sip_hdr_end -
320 sip_header->sip_hdr_current - 2;
322 *header = parsed_header;
324 sip_header->sip_hdr_parsed = *header;
325 return (0);
329 * Error-Info = "Error-Info" HCOLON error-uri *(COMMA error-uri)
330 * error-uri = LAQUOT absoluteURI RAQUOT *(SEMI generic-param)
333 sip_parse_errorinfo_header(_sip_header_t *sip_header,
334 sip_parsed_header_t **header)
336 return (sip_parse_hdr_parser3(sip_header, header, SIP_STR_VAL, B_TRUE));
340 * Expires = "Expires" HCOLON delta-seconds
343 sip_parse_expire_header(_sip_header_t *sip_header,
344 sip_parsed_header_t **header)
346 return (sip_parse_hdr_parser2(sip_header, header, SIP_INT_VAL));
350 * In-Reply-To = "In-Reply-To" HCOLON callid *(COMMA callid)
353 sip_parse_inreplyto_header(_sip_header_t *sip_header,
354 sip_parsed_header_t **header)
356 return (sip_parse_hdr_parser1(sip_header, header, SIP_NUL));
360 * RSeq = "RSeq" HCOLON response-num
363 sip_parse_rseq(_sip_header_t *sip_header, sip_parsed_header_t **header)
365 int r;
366 sip_hdr_value_t *rseq_value;
368 r = sip_parse_hdr_parser2(sip_header, header, SIP_INT_VAL);
370 * Additionally, a value of 0 is bad_value
372 if (sip_header->sip_hdr_parsed != NULL &&
373 sip_header->sip_hdr_parsed->value != NULL) {
374 rseq_value = (sip_hdr_value_t *)
375 sip_header->sip_hdr_parsed->value;
376 if (rseq_value->int_val == 0)
377 rseq_value->sip_value_state = SIP_VALUE_BAD;
379 return (r);
383 * Min-Expires = "Min-Expires" HCOLON delta-seconds
386 sip_parse_minexpire_header(_sip_header_t *sip_header,
387 sip_parsed_header_t **header)
389 return (sip_parse_hdr_parser2(sip_header, header, SIP_INT_VAL));
393 * MIME-Version = "MIME-Version" HCOLON 1*DIGIT "." 1*DIGIT
396 sip_parse_mimeversion_header(_sip_header_t *sip_header,
397 sip_parsed_header_t **header)
399 return (sip_parse_hdr_parser4(sip_header, header));
403 * Organization = "Organization" HCOLON [TEXT-UTF8-TRIM]
406 sip_parse_org_header(_sip_header_t *sip_header,
407 sip_parsed_header_t **header)
409 if (sip_is_empty_hdr(sip_header))
410 return (sip_parse_hdr_empty(sip_header, header));
411 return (sip_parse_hdr_parser4(sip_header, header));
415 * Priority = "Priority" HCOLON priority-val
416 * priority-val = "emergency" | "urgent" | "normal" | "non-urgent" | other
417 * other = token
420 sip_parse_priority_header(_sip_header_t *sip_header,
421 sip_parsed_header_t **header)
423 return (sip_parse_hdr_parser4(sip_header, header));
427 * Reply-To = "Reply-To" HCOLON rplyto-spec
428 * rplyto-spec = (name-addr | addr-spec) *(SEMI rplyto-param)
429 * rplyto-param = generic-param
430 * name-addr = [ display-name ] LAQUOT addr-spec RAQUOT
431 * addr-spec = SIP-URI | SIPS-URI | absolute URI
434 sip_parse_replyto_header(_sip_header_t *sip_header,
435 sip_parsed_header_t **header)
437 return (sip_parse_hdr_parser3(sip_header, header, SIP_STRS_VAL,
438 B_TRUE));
442 * PRIVACY = "Privacy" HCOLON priv-value *(COMMA priv-value)
443 * priv-value = "header" / "session" / "user" / "none" / "critical"
444 * / token / id
447 sip_parse_privacy_header(_sip_header_t *sip_header,
448 sip_parsed_header_t **header)
450 return (sip_parse_hdr_parser1(sip_header, header, SIP_NUL));
455 * Require = "Require" HCOLON option-tag * (COMMA option-tag)
458 sip_parse_require_header(_sip_header_t *sip_header,
459 sip_parsed_header_t **header)
461 return (sip_parse_hdr_parser1(sip_header, header, SIP_NUL));
465 * Retry-After = "Retry-After" HCOLON delta-seconds [ comment ] *
466 * (SEMI retry-param)
467 * retry-param = "duration" EQUAL delta-seconds
470 sip_parse_retryaft_header(_sip_header_t *sip_header,
471 sip_parsed_header_t **header)
473 sip_parsed_header_t *parsed_header;
474 sip_hdr_value_t *value = NULL;
475 int ret;
477 if ((ret = sip_prim_parsers(sip_header, header)) != 0)
478 return (ret);
480 if (*header != NULL)
481 return (0);
483 parsed_header = calloc(1, sizeof (sip_parsed_header_t));
484 if (parsed_header == NULL)
485 return (ENOMEM);
486 parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1;
487 parsed_header->sip_header = sip_header;
489 value = calloc(1, sizeof (sip_hdr_value_t));
490 if (value == NULL) {
491 sip_free_phdr(parsed_header);
492 return (ENOMEM);
495 parsed_header->value = (sip_value_t *)value;
496 value->sip_value_start = sip_header->sip_hdr_current;
497 value->sip_value_header = parsed_header;
499 ret = sip_atoi(sip_header, &(value->intstr_int));
500 if (ret != 0)
501 value->sip_value_state = SIP_VALUE_BAD;
502 if (sip_find_token(sip_header, SIP_LPAR) == 0) {
503 value->intstr_str_ptr = sip_header->sip_hdr_current;
504 if (sip_find_token(sip_header, SIP_RPAR) == 0) {
505 value->intstr_str_len =
506 sip_header->sip_hdr_current -
507 value->intstr_str_ptr - 1;
508 if (sip_find_token(sip_header, SIP_SEMI) == 0) {
509 sip_header->sip_hdr_current--;
510 (void) sip_parse_params(sip_header,
511 &(value->sip_param_list));
513 } else {
514 value->sip_value_state = SIP_VALUE_BAD;
515 return (EPROTO);
517 } else {
518 value->intstr_str_ptr = NULL;
519 value->intstr_str_len = 0;
522 * from value start, search if parameter list
524 sip_header->sip_hdr_current = value->sip_value_start;
525 if (sip_find_token(sip_header, SIP_SEMI) == 0) {
526 sip_header->sip_hdr_current--;
527 (void) sip_parse_params(sip_header,
528 &(value->sip_param_list));
532 *header = parsed_header;
533 sip_header->sip_hdr_parsed = *header;
534 return (0);
538 * Server = "Server" HCOLON servel-val *(LWS server-val)
539 * servel-val = product|comment
540 * product = token [SLASH version]
541 * version = token
542 * Treated as one single string
545 sip_parse_server_header(_sip_header_t *sip_header, sip_parsed_header_t **header)
547 return (sip_parse_hdr_parser4(sip_header, header));
551 * Subject = ("Subject" | "s")HCOLON [TEXT-UTF8-TRIM]
554 sip_parse_subject_header(_sip_header_t *sip_header,
555 sip_parsed_header_t **header)
557 if (sip_is_empty_hdr(sip_header))
558 return (sip_parse_hdr_empty(sip_header, header));
559 return (sip_parse_hdr_parser4(sip_header, header));
563 * Supported = ("Supported" | "k") HCOLON [option-tag * (COMMA option-tag) ]
566 sip_parse_support_header(_sip_header_t *sip_header,
567 sip_parsed_header_t **header)
569 if (sip_is_empty_hdr(sip_header))
570 return (sip_parse_hdr_empty(sip_header, header));
571 return (sip_parse_hdr_parser1(sip_header, header, SIP_NUL));
575 * Timestamp = "Timestamp" HCOLON 1*DIGIT ["." *(DIGIT)] [LWS delay]
578 sip_parse_timestamp_header(_sip_header_t *sip_header,
579 sip_parsed_header_t **header)
581 sip_parsed_header_t *parsed_header;
582 sip_hdr_value_t *value = NULL;
583 int ret;
585 if ((ret = sip_prim_parsers(sip_header, header)) != 0)
586 return (ret);
588 if (*header != NULL)
589 return (0);
591 parsed_header = calloc(1, sizeof (sip_parsed_header_t));
592 if (parsed_header == NULL)
593 return (ENOMEM);
594 parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1;
595 parsed_header->sip_header = sip_header;
597 value = calloc(1, sizeof (sip_hdr_value_t));
598 if (value == NULL) {
599 sip_free_phdr(parsed_header);
600 return (ENOMEM);
602 parsed_header->value = (sip_value_t *)value;
604 value->sip_value_start = sip_header->sip_hdr_current;
605 value->sip_value_header = parsed_header;
607 if (sip_skip_white_space(sip_header) != 0) {
608 value->sip_value_state = SIP_VALUE_BAD;
609 return (EPROTO);
611 value->strs1_val_ptr = sip_header->sip_hdr_current;
613 if (sip_find_white_space(sip_header) == 0) {
615 * timestamp and delay, timestamp in str1, delay in str2
617 value->strs1_val_len = sip_header->sip_hdr_current -
618 value->strs1_val_ptr;
619 (void) sip_skip_white_space(sip_header);
621 value->strs2_val_ptr = sip_header->sip_hdr_current;
622 if (sip_find_cr(sip_header) != 0) {
623 value->sip_value_state = SIP_VALUE_BAD;
624 return (EPROTO);
626 if (sip_header->sip_hdr_current < value->strs2_val_ptr) {
627 value->strs2_val_ptr = NULL;
628 value->strs2_val_len = 0;
629 } else {
630 value->strs2_val_len = sip_header->sip_hdr_current -
631 value->strs2_val_ptr;
633 } else {
635 * no delay information
637 value->strs1_val_len = sip_header->sip_hdr_current
638 - value->strs1_val_ptr;
639 value->strs2_val_ptr = NULL;
640 value->strs2_val_len = 0;
643 *header = parsed_header;
644 sip_header->sip_hdr_parsed = *header;
646 return (0);
649 * Unsupported = "Unsupported" HCOLON option-tag * (COMMA option-tag)
652 sip_parse_usupport_header(_sip_header_t *sip_header,
653 sip_parsed_header_t **header)
655 return (sip_parse_hdr_parser1(sip_header, header, SIP_NUL));
659 * User-Agent = "User-Agent" HCOLON server-val * (LWS server-val)
660 * servel-val = product |comment
661 * product = token [SLASH version]
662 * version = token
665 sip_parse_useragt_header(_sip_header_t *sip_header,
666 sip_parsed_header_t **header)
668 return (sip_parse_hdr_parser4(sip_header, header));
672 * Warning = "Warning" HCOLON warning-value *(COMMA warning-value)
673 * warning-value = warn-code SP warn-agent SP warn-text
674 * warn-code = 3DIGIT
675 * warn-agent = hostport | pseudonym ;
676 * the name or pseudonym of the server adding;
677 * the Warning header, for use in debugging
678 * warn-text = quoted-string
679 * pseudonym = token
682 sip_parse_warn_header(_sip_header_t *sip_header, sip_parsed_header_t **header)
684 sip_parsed_header_t *parsed_header;
685 int ret;
686 sip_hdr_value_t *value = NULL;
687 sip_hdr_value_t *last_value = NULL;
689 if ((ret = sip_prim_parsers(sip_header, header)) != 0)
690 return (ret);
692 if (*header != NULL)
693 return (0);
695 parsed_header = calloc(1, sizeof (sip_parsed_header_t));
696 if (parsed_header == NULL)
697 return (ENOMEM);
698 parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1;
699 parsed_header->sip_header = sip_header;
701 while (sip_header->sip_hdr_current < sip_header->sip_hdr_end) {
702 value = calloc(1, sizeof (sip_hdr_value_t));
703 if (value == NULL) {
704 sip_free_phdr(parsed_header);
705 return (ENOMEM);
708 if (last_value != NULL)
709 last_value->sip_next_value = value;
710 else
711 parsed_header->value = (sip_value_t *)value;
713 value->sip_value_start = sip_header->sip_hdr_current;
714 value->sip_value_header = parsed_header;
716 ret = sip_atoi(sip_header, &value->warn_code);
717 if (ret != 0 || value->warn_code < 100 ||
718 value->warn_code > 999) {
719 value->sip_value_state = SIP_VALUE_BAD;
720 goto get_next_val;
722 if (sip_skip_white_space(sip_header) != 0) {
723 value->sip_value_state = SIP_VALUE_BAD;
724 goto get_next_val;
726 value->warn_agt_ptr = sip_header->sip_hdr_current;
728 if (sip_find_token(sip_header, SIP_QUOTE) == 0) {
730 * get warning agent
732 sip_header->sip_hdr_current--;
733 (void) sip_reverse_skip_white_space(sip_header);
734 value->warn_agt_len = sip_header->sip_hdr_current -
735 value->warn_agt_ptr - 1;
736 if (value->warn_agt_len <= 0) {
737 value->warn_agt_ptr = NULL;
738 value->sip_value_state = SIP_VALUE_BAD;
742 * We will have a SIP_QUOTE here
744 (void) sip_find_token(sip_header, SIP_QUOTE);
746 value->warn_text_ptr = sip_header->sip_hdr_current;
747 if (sip_find_token(sip_header, SIP_QUOTE) == 0) {
748 value->warn_text_len =
749 sip_header->sip_hdr_current -
750 value->warn_text_ptr - 1;
751 } else {
752 value->sip_value_state = SIP_VALUE_BAD;
753 goto get_next_val;
755 } else
757 * warning text must present
759 value->sip_value_state = SIP_VALUE_BAD;
761 get_next_val:
762 if (sip_find_token(sip_header, SIP_COMMA) != 0)
763 break;
764 value->sip_value_end = sip_header->sip_hdr_current - 1;
765 last_value = value;
766 (void) sip_skip_white_space(sip_header);
769 *header = parsed_header;
771 sip_header->sip_hdr_parsed = *header;
772 return (0);
776 * Parse RAck header
777 * "RAck" HCOLON response-num LWS CSeq-num LWS Method
778 * response-num = 1*DIGIT
779 * CSeq-num = 1*DIGIT
782 sip_parse_rack(_sip_header_t *sip_header, sip_parsed_header_t **header)
784 sip_parsed_header_t *parsed_header;
785 sip_hdr_value_t *rack_value;
786 int len;
787 char *tmp_ptr;
788 int i;
789 int ret;
791 if ((ret = sip_prim_parsers(sip_header, header)) != 0)
792 return (ret);
794 if (*header != NULL)
795 return (0);
797 parsed_header = calloc(1, sizeof (sip_parsed_header_t));
798 if (parsed_header == NULL)
799 return (ENOMEM);
800 parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1;
801 parsed_header->sip_header = sip_header;
803 parsed_header->value = calloc(1, sizeof (sip_hdr_value_t));
804 if (parsed_header->value == NULL) {
805 free(parsed_header);
806 return (ENOMEM);
808 rack_value = (sip_hdr_value_t *)parsed_header->value;
809 rack_value->sip_value_version = SIP_VALUE_VERSION_1;
810 rack_value->sip_value_start = sip_header->sip_hdr_current;
811 rack_value->sip_value_header = parsed_header;
812 if (sip_atoi(sip_header, &rack_value->rack_resp) ||
813 rack_value->rack_resp == 0) {
814 rack_value->sip_value_state = SIP_VALUE_BAD;
815 rack_value->sip_value_end = sip_header->sip_hdr_end - 2;
816 goto rack_parse_done;
818 rack_value->sip_value_header = parsed_header;
820 * Get cseq.
822 if (sip_skip_white_space(sip_header) != 0) {
823 rack_value->sip_value_state = SIP_VALUE_BAD;
824 rack_value->sip_value_end = sip_header->sip_hdr_end - 2;
825 goto rack_parse_done;
827 if (sip_atoi(sip_header, &rack_value->rack_cseq)) {
828 rack_value->sip_value_state = SIP_VALUE_BAD;
829 rack_value->sip_value_end = sip_header->sip_hdr_end - 2;
830 goto rack_parse_done;
833 * Get method.
835 if (sip_skip_white_space(sip_header) != 0) {
836 rack_value->sip_value_state = SIP_VALUE_BAD;
837 rack_value->sip_value_end = sip_header->sip_hdr_end - 2;
838 goto rack_parse_done;
841 tmp_ptr = sip_header->sip_hdr_current;
842 if (sip_find_white_space(sip_header)) {
843 rack_value->sip_value_state = SIP_VALUE_BAD;
844 rack_value->sip_value_end = sip_header->sip_hdr_end - 2;
845 goto rack_parse_done;
848 len = sip_header->sip_hdr_current - tmp_ptr;
850 for (i = 1; i < MAX_SIP_METHODS; i++) {
851 if (strncmp(sip_methods[i].name, tmp_ptr, len) == 0)
852 break;
855 if (i >= MAX_SIP_METHODS) {
856 rack_value->sip_value_state = SIP_VALUE_BAD;
857 rack_value->sip_value_end = sip_header->sip_hdr_end - 2;
858 goto rack_parse_done;
861 rack_value->rack_method = i;
862 rack_value->sip_value_end = sip_header->sip_hdr_current;
864 rack_parse_done:
865 sip_header->sip_hdr_parsed = parsed_header;
867 *header = parsed_header;
868 return (0);
872 * Allow = "Allow" HCOLON [Method *(COMMA Method)]
875 sip_parse_allow_events_header(_sip_header_t *sip_header,
876 sip_parsed_header_t **header)
878 return (sip_parse_hdr_parser1(sip_header, header, SIP_NUL));
882 * Event = ( "Event" / "o" ) HCOLON event-type
883 * *( SEMI event-param )
884 * event-type = event-package *( "." event-template )
885 * event-package = token-nodot
886 * event-template = token-nodot
887 * token-nodot = 1*( alphanum / "-" / "!" / "%" / "*"
888 * / "_" / "+" / "`" / "'" / "~" )
889 * event-param = generic-param / ( "id" EQUAL token )
892 sip_parse_event_header(_sip_header_t *sip_header, sip_parsed_header_t **header)
894 return (sip_parse_hdr_parser1(sip_header, header, SIP_NUL));
898 * Subscription-State = "Subscription-State" HCOLON substate-value
899 * *( SEMI subexp-params )
900 * substate-value = "active" / "pending" / "terminated"
901 * / extension-substate
902 * extension-substate = token
903 * subexp-params = ("reason" EQUAL event-reason-value)
904 * / ("expires" EQUAL delta-seconds)*
905 * / ("retry-after" EQUAL delta-seconds)
906 * / generic-param
907 * event-reason-value = "deactivated"
908 * / "probation"
909 * / "rejected"
910 * / "timeout"
911 * / "giveup"
912 * / "noresource"
913 * / event-reason-extension
914 * event-reason-extension = token
917 sip_parse_substate_header(_sip_header_t *sip_header,
918 sip_parsed_header_t **header)
920 return (sip_parse_hdr_parser1(sip_header, header, SIP_NUL));
924 * Authorization = "Authorization" HCOLON credentials
925 * credentials = ("Digest" LWS digest-response)
926 * / other-response
927 * digest-response = dig-resp *(COMMA dig-resp)
928 * dig-resp = username / realm / nonce / digest-uri
929 * / dresponse / algorithm / cnonce
930 * / opaque / message-qop
931 * / nonce-count / auth-param
932 * username = "username" EQUAL username-value
933 * username-value = quoted-string
934 * digest-uri = "uri" EQUAL LDQUOT digest-uri-value RDQUOT
935 * digest-uri-value = rquest-uri ; Equal to request-uri as specified
936 * by HTTP/1.1
937 * message-qop = "qop" EQUAL qop-value
938 * cnonce = "cnonce" EQUAL cnonce-value
939 * cnonce-value = nonce-value
940 * nonce-count = "nc" EQUAL nc-value
941 * nc-value = 8LHEX
942 * dresponse = "response" EQUAL request-digest
943 * request-digest = LDQUOT 32LHEX RDQUOT
944 * auth-param = auth-param-name EQUAL
945 * ( token / quoted-string )
946 * auth-param-name = token
947 * other-response = auth-scheme LWS auth-param
948 * *(COMMA auth-param)
949 * auth-scheme = token
952 sip_parse_author_header(_sip_header_t *sip_header,
953 sip_parsed_header_t **header)
955 return (sip_parse_hdr_parser5(sip_header, header, B_TRUE));
959 * Authentication-Info = "Authentication-Info" HCOLON ainfo
960 * *(COMMA ainfo)
961 * ainfo = nextnonce / message-qop
962 * / response-auth / cnonce
963 * / nonce-count
964 * nextnonce = "nextnonce" EQUAL nonce-value
965 * response-auth = "rspauth" EQUAL response-digest
966 * response-digest = LDQUOT *LHEX RDQUOT
970 sip_parse_ainfo_header(_sip_header_t *sip_header,
971 sip_parsed_header_t **header)
973 return (sip_parse_hdr_parser1(sip_header, header, SIP_NUL));
977 * Proxy-Authenticate = "Proxy-Authenticate" HCOLON challenge
978 * challenge = ("Digest" LWS digest-cln *(COMMA digest-cln))
979 * / other-challenge
980 * other-challenge = auth-scheme LWS auth-param
981 * *(COMMA auth-param)
982 * digest-cln = realm / domain / nonce
983 * / opaque / stale / algorithm
984 * / qop-options / auth-param
985 * realm = "realm" EQUAL realm-value
986 * realm-value = quoted-string
987 * domain = "domain" EQUAL LDQUOT URI
988 * *( 1*SP URI ) RDQUOT
989 * URI = absoluteURI / abs-path
990 * nonce = "nonce" EQUAL nonce-value
991 * nonce-value = quoted-string
992 * opaque = "opaque" EQUAL quoted-string
993 * stale = "stale" EQUAL ( "true" / "false" )
994 * algorithm = "algorithm" EQUAL ( "MD5" / "MD5-sess"
995 * / token )
996 * qop-options = "qop" EQUAL LDQUOT qop-value
997 * *("," qop-value) RDQUOT
998 * qop-value = "auth" / "auth-int" / token
1002 sip_parse_pauthen_header(_sip_header_t *sip_header,
1003 sip_parsed_header_t **header)
1005 return (sip_parse_hdr_parser5(sip_header, header, B_TRUE));
1009 * Proxy-Authorization = "Proxy-Authorization" HCOLON credentials
1012 sip_parse_pauthor_header(_sip_header_t *sip_header,
1013 sip_parsed_header_t **header)
1015 return (sip_parse_hdr_parser5(sip_header, header, B_TRUE));
1019 * Proxy-Require = "Proxy-Require" HCOLON option-tag
1020 * *(COMMA option-tag)
1021 * option-tag = token
1024 sip_parse_preq_header(_sip_header_t *sip_header,
1025 sip_parsed_header_t **header)
1027 return (sip_parse_hdr_parser1(sip_header, header, SIP_NUL));
1031 * WWW-Authenticate = "WWW-Authenticate" HCOLON challenge
1032 * extension-header = header-name HCOLON header-value
1033 * header-name = token
1034 * header-value = *(TEXT-UTF8char / UTF8-CONT / LWS)
1035 * message-body = *OCTET
1039 sip_parse_wauthen_header(_sip_header_t *sip_header,
1040 sip_parsed_header_t **header)
1042 return (sip_parse_hdr_parser5(sip_header, header, B_TRUE));
1046 * Call-ID = ( "Call-ID" / "i" ) HCOLON callid
1049 sip_parse_cid_header(_sip_header_t *sip_header, sip_parsed_header_t **header)
1051 return (sip_parse_hdr_parser4(sip_header, header));
1055 * CSeq = "CSeq" HCOLON 1*DIGIT LWS Method
1058 sip_parse_cseq_header(_sip_header_t *sip_header, sip_parsed_header_t **header)
1060 sip_parsed_header_t *parsed_header;
1061 sip_hdr_value_t *cseq_value;
1062 int len;
1063 char *tmp_ptr;
1064 int i;
1065 int ret;
1067 if ((ret = sip_prim_parsers(sip_header, header)) != 0)
1068 return (ret);
1070 if (*header != NULL)
1071 return (0);
1073 parsed_header = calloc(1, sizeof (sip_parsed_header_t));
1074 if (parsed_header == NULL)
1075 return (ENOMEM);
1076 parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1;
1077 parsed_header->sip_header = sip_header;
1079 parsed_header->value = calloc(1, sizeof (sip_hdr_value_t));
1080 if (parsed_header->value == NULL) {
1081 free(parsed_header);
1082 return (ENOMEM);
1084 cseq_value = (sip_hdr_value_t *)parsed_header->value;
1085 cseq_value->sip_value_version = SIP_VALUE_VERSION_1;
1086 cseq_value->sip_value_start = sip_header->sip_hdr_current;
1087 if (sip_atoi(sip_header, &cseq_value->cseq_num)) {
1088 cseq_value->sip_value_state = SIP_VALUE_BAD;
1089 cseq_value->sip_value_end = sip_header->sip_hdr_end - 2;
1090 goto cseq_parse_done;
1092 cseq_value->sip_value_header = parsed_header;
1094 * Get method.
1096 if (sip_skip_white_space(sip_header) != 0) {
1097 cseq_value->sip_value_state = SIP_VALUE_BAD;
1098 cseq_value->sip_value_end = sip_header->sip_hdr_end - 2;
1099 goto cseq_parse_done;
1102 tmp_ptr = sip_header->sip_hdr_current;
1104 if (sip_find_white_space(sip_header)) {
1105 cseq_value->sip_value_state = SIP_VALUE_BAD;
1106 cseq_value->sip_value_end = sip_header->sip_hdr_current;
1107 goto cseq_parse_done;
1110 len = sip_header->sip_hdr_current - tmp_ptr;
1112 for (i = 1; i < MAX_SIP_METHODS; i++) {
1113 if (strncmp(sip_methods[i].name, tmp_ptr, len) == 0)
1114 break;
1117 if (i >= MAX_SIP_METHODS) {
1118 cseq_value->sip_value_state = SIP_VALUE_BAD;
1119 cseq_value->sip_value_end = sip_header->sip_hdr_current;
1120 goto cseq_parse_done;
1123 cseq_value->cseq_method = i;
1124 cseq_value->sip_value_end = sip_header->sip_hdr_current;
1125 cseq_parse_done:
1127 sip_header->sip_hdr_parsed = parsed_header;
1129 *header = parsed_header;
1130 return (0);
1135 * Via = ( "Via" / "v" ) HCOLON via-parm *(COMMA via-parm)
1136 * via-parm = sent-protocol LWS sent-by *( SEMI via-params )
1137 * via-params = via-ttl / via-maddr
1138 * / via-received / via-branch
1139 * / via-extension
1140 * via-ttl = "ttl" EQUAL ttl
1141 * via-maddr = "maddr" EQUAL host
1142 * via-received = "received" EQUAL (IPv4address / IPv6address)
1143 * via-branch = "branch" EQUAL token
1144 * via-extension = generic-param
1145 * sent-protocol = protocol-name SLASH protocol-version
1146 * SLASH transport
1147 * protocol-name = "SIP" / token
1148 * protocol-version = token
1149 * transport = "UDP" / "TCP" / "TLS" / "SCTP"
1150 * / other-transport
1151 * sent-by = host [ COLON port ]
1152 * ttl = 1*3DIGIT ; 0 to 255
1154 * There can be multiple via headers we always append the header.
1157 sip_parse_via_header(_sip_header_t *sip_header, sip_parsed_header_t **header)
1159 sip_parsed_header_t *parsed_header;
1160 int ret;
1161 sip_hdr_value_t *value = NULL;
1162 sip_hdr_value_t *last_value = NULL;
1164 if ((ret = sip_prim_parsers(sip_header, header)) != 0)
1165 return (ret);
1167 if (*header != NULL)
1168 return (0);
1170 parsed_header = calloc(1, sizeof (sip_parsed_header_t));
1171 if (parsed_header == NULL)
1172 return (ENOMEM);
1173 parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1;
1174 parsed_header->sip_header = sip_header;
1176 while (sip_header->sip_hdr_current < sip_header->sip_hdr_end) {
1178 value = calloc(1, sizeof (sip_hdr_value_t));
1179 if (value == NULL) {
1180 sip_free_phdr(parsed_header);
1181 return (ENOMEM);
1183 if (last_value != NULL)
1184 last_value->sip_next_value = value;
1185 else
1186 parsed_header->value = (sip_value_t *)value;
1188 value->sip_value_version = SIP_VALUE_VERSION_1;
1189 value->sip_value_start = sip_header->sip_hdr_current;
1190 value->sip_value_header = parsed_header;
1191 value->via_protocol_name.sip_str_ptr =
1192 sip_header->sip_hdr_current;
1195 * Check to see if there is a version number
1197 if (sip_get_protocol_version(sip_header,
1198 &value->via_protocol) != 0) {
1199 if (sip_goto_next_value(sip_header) != 0) {
1200 sip_free_phdr(parsed_header);
1201 return (EPROTO);
1203 value->sip_value_state = SIP_VALUE_BAD;
1204 goto get_next_via_value;
1207 if (sip_find_token(sip_header, SIP_SLASH) != 0) {
1208 if (sip_goto_next_value(sip_header) != 0) {
1209 sip_free_phdr(parsed_header);
1210 return (EPROTO);
1212 value->sip_value_state = SIP_VALUE_BAD;
1213 goto get_next_via_value;
1216 if (sip_skip_white_space(sip_header) != 0) {
1217 if (sip_goto_next_value(sip_header) != 0) {
1218 sip_free_phdr(parsed_header);
1219 return (EPROTO);
1221 value->sip_value_state = SIP_VALUE_BAD;
1222 goto get_next_via_value;
1225 value->via_protocol_transport.sip_str_ptr =
1226 sip_header->sip_hdr_current;
1227 if (sip_find_white_space(sip_header) != 0) {
1228 if (sip_goto_next_value(sip_header) != 0) {
1229 sip_free_phdr(parsed_header);
1230 return (EPROTO);
1232 value->sip_value_state = SIP_VALUE_BAD;
1233 goto get_next_via_value;
1236 value->via_protocol_transport.sip_str_len =
1237 sip_header->sip_hdr_current -
1238 value->via_protocol_transport.sip_str_ptr;
1240 if (sip_skip_white_space(sip_header) != 0) {
1241 if (sip_goto_next_value(sip_header) != 0) {
1242 sip_free_phdr(parsed_header);
1243 return (EPROTO);
1245 value->sip_value_state = SIP_VALUE_BAD;
1246 goto get_next_via_value;
1249 value->via_sent_by_host.sip_str_ptr =
1250 sip_header->sip_hdr_current;
1251 if (*sip_header->sip_hdr_current == '[') {
1252 if (sip_find_token(sip_header, ']')) {
1253 if (sip_goto_next_value(sip_header) != 0) {
1254 sip_free_phdr(parsed_header);
1255 return (EPROTO);
1257 value->sip_value_state = SIP_VALUE_BAD;
1258 goto get_next_via_value;
1260 } else if (sip_find_separator(sip_header, SIP_SEMI, SIP_COMMA,
1261 SIP_HCOLON, B_FALSE)) {
1262 if (sip_goto_next_value(sip_header) != 0) {
1263 sip_free_phdr(parsed_header);
1264 return (EPROTO);
1266 value->sip_value_state = SIP_VALUE_BAD;
1267 goto get_next_via_value;
1269 value->via_sent_by_host.sip_str_len =
1270 sip_header->sip_hdr_current -
1271 value->via_sent_by_host.sip_str_ptr;
1273 if (sip_skip_white_space(sip_header) != 0) {
1274 if (sip_goto_next_value(sip_header) != 0) {
1275 sip_free_phdr(parsed_header);
1276 return (EPROTO);
1278 value->sip_value_state = SIP_VALUE_BAD;
1279 goto get_next_via_value;
1282 if (*sip_header->sip_hdr_current == SIP_HCOLON) {
1283 sip_header->sip_hdr_current++;
1285 * We have a port number
1287 if (sip_atoi(sip_header, &value->via_sent_by_port) !=
1288 0) {
1289 if (sip_goto_next_value(sip_header) != 0) {
1290 sip_free_phdr(parsed_header);
1291 return (EPROTO);
1293 value->sip_value_state = SIP_VALUE_BAD;
1294 goto get_next_via_value;
1300 * Do some sanity checking.
1301 * This should be replaced by a v4/v6 address check.
1303 if (value->via_sent_by_host.sip_str_len == 0 ||
1304 (!isalnum(*value->via_sent_by_host.sip_str_ptr) &&
1305 *value->via_sent_by_host.sip_str_ptr != '[')) {
1306 if (sip_goto_next_value(sip_header) != 0) {
1307 sip_free_phdr(parsed_header);
1308 return (EPROTO);
1310 value->sip_value_state = SIP_VALUE_BAD;
1311 goto get_next_via_value;
1314 ret = sip_parse_params(sip_header, &value->sip_param_list);
1315 if (ret == EPROTO) {
1316 value->sip_value_state = SIP_VALUE_BAD;
1317 } else if (ret != 0) {
1318 sip_free_phdr(parsed_header);
1319 return (ret);
1321 get_next_via_value:
1322 value->sip_value_end = sip_header->sip_hdr_current;
1324 if (sip_find_token(sip_header, SIP_COMMA) != 0)
1325 break;
1326 last_value = value;
1327 (void) sip_skip_white_space(sip_header);
1330 sip_header->sip_hdr_parsed = parsed_header;
1332 *header = parsed_header;
1333 return (0);
1337 * Max-Forwards = "Max-Forwards" HCOLON 1*DIGIT
1340 sip_parse_maxf_header(_sip_header_t *sip_header, sip_parsed_header_t **header)
1342 return (sip_parse_hdr_parser2(sip_header, header, SIP_INT_VAL));
1346 * Content-Type = ( "Content-Type" / "c" ) HCOLON media-type
1347 * media-type = m-type SLASH m-subtype *(SEMI m-parameter)
1348 * m-type = discrete-type / composite-type
1349 * discrete-type = "text" / "image" / "audio" / "video"
1350 * / "application" / extension-token
1351 * composite-type = "message" / "multipart" / extension-token
1352 * extension-token = ietf-token / x-token
1353 * ietf-token = token
1354 * x-token = "x-" token
1355 * m-subtype = extension-token / iana-token
1356 * iana-token = token
1357 * m-parameter = m-attribute EQUAL m-value
1358 * m-attribute = token
1359 * m-value = token / quoted-string
1362 sip_parse_ctype_header(_sip_header_t *sip_header, sip_parsed_header_t **header)
1364 return (sip_parse_hdr_parser1(sip_header, header, SIP_SLASH));
1368 * Content-Length = ( "Content-Length" / "l" ) HCOLON 1*DIGIT
1371 sip_parse_clen_header(_sip_header_t *sip_header, sip_parsed_header_t **header)
1373 return (sip_parse_hdr_parser2(sip_header, header, SIP_INT_VAL));
1377 * Generic parser for Contact, From, To, Route and Record-Route headers
1379 * Contact = ("Contact" / "m" ) HCOLON
1380 * ( STAR / (contact-param *(COMMA contact-param)))
1381 * contact-param = (name-addr / addr-spec) *(SEMI contact-params)
1382 * name-addr = [ display-name ] LAQUOT addr-spec RAQUOT
1383 * addr-spec = SIP-URI / SIPS-URI / absoluteURI
1384 * display-name = *(token LWS)/ quoted-string
1385 * contact-params = c-p-q / c-p-expires
1386 * / contact-extension
1388 * From = ( "From" / "f" ) HCOLON from-spec
1389 * from-spec = ( name-addr / addr-spec )
1390 * *( SEMI from-param )
1391 * from-param = tag-param / generic-param
1392 * tag-param = "tag" EQUAL token
1394 * To = ( "To" / "t" ) HCOLON ( name-addr
1395 * / addr-spec ) *( SEMI to-param )
1396 * to-param = tag-param / generic-param
1398 * Route = "Route" HCOLON route-param *(COMMA route-param)
1399 * route-param = name-addr *( SEMI rr-param )
1401 * Record-Route = "Record-Route" HCOLON rec-route *(COMMA rec-route)
1402 * rec-route = name-addr *( SEMI rr-param )
1403 * rr-param = generic-param
1405 * We could have multiple values for these headers. For the ones that have
1406 * a display name we will have a LAQUOT/RAQUOT. If we encounter an error
1407 * when parsing a value, we mark the value as bad and start paring the
1408 * next value, if present. Before we start parsing the next value, we
1409 * check for any parameters, if present.
1412 sip_parse_cftr_header(_sip_header_t *sip_header, sip_parsed_header_t **header)
1414 sip_parsed_header_t *parsed_header;
1415 char *tmp_ptr;
1416 char *tmp_ptr_2;
1417 int ret;
1418 sip_hdr_value_t *value = NULL;
1419 sip_hdr_value_t *last_value = NULL;
1421 if ((ret = sip_prim_parsers(sip_header, header)) != 0)
1422 return (ret);
1424 if (*header != NULL)
1425 return (0);
1427 parsed_header = calloc(1, sizeof (sip_parsed_header_t));
1428 if (parsed_header == NULL)
1429 return (ENOMEM);
1430 parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1;
1431 parsed_header->sip_header = sip_header;
1432 while (sip_header->sip_hdr_current < sip_header->sip_hdr_end) {
1433 boolean_t quoted_name = B_FALSE;
1435 value = calloc(1, sizeof (sip_hdr_value_t));
1436 if (value == NULL) {
1437 sip_free_cftr_header(parsed_header);
1438 return (ENOMEM);
1440 if (last_value != NULL)
1441 last_value->sip_next_value = value;
1442 else
1443 parsed_header->value = (sip_value_t *)value;
1444 if (*sip_header->sip_hdr_current == SIP_QUOTE) {
1445 sip_header->sip_hdr_current++;
1446 quoted_name = B_TRUE;
1448 value->sip_value_version = SIP_VALUE_VERSION_1;
1449 value->sip_value_start = sip_header->sip_hdr_current;
1450 value->sip_value_header = parsed_header;
1452 * let's see if there is a display name
1454 if (*sip_header->sip_hdr_current != SIP_LAQUOT) {
1456 tmp_ptr = sip_header->sip_hdr_current;
1458 * According to 20.10 '<' may not have a leading
1459 * space.
1461 if (quoted_name &&
1462 sip_find_token(sip_header, SIP_QUOTE) != 0) {
1463 if (sip_goto_next_value(sip_header) != 0) {
1464 sip_free_cftr_header(parsed_header);
1465 return (EPROTO);
1467 value->sip_value_state = SIP_VALUE_BAD;
1468 goto get_next_cftr_value;
1469 } else if (sip_find_separator(sip_header, SIP_SEMI,
1470 SIP_LAQUOT, SIP_COMMA, B_TRUE) != 0) {
1472 * only a uri.
1474 value->cftr_uri.sip_str_ptr = tmp_ptr;
1475 value->cftr_uri.sip_str_len =
1476 sip_header->sip_hdr_current - tmp_ptr;
1478 * It's an error not to have a uri.
1480 if (value->cftr_uri.sip_str_len == 0) {
1481 if (sip_goto_next_value(sip_header) !=
1482 0) {
1483 sip_free_cftr_header(
1484 parsed_header);
1485 return (EPROTO);
1487 value->sip_value_state = SIP_VALUE_BAD;
1488 goto get_next_cftr_value;
1490 goto get_next_cftr_value;
1493 * This is needed to get rid of leading white spaces of
1494 * display name or uri
1496 --sip_header->sip_hdr_current;
1497 (void) sip_reverse_skip_white_space(sip_header);
1498 ++sip_header->sip_hdr_current;
1499 tmp_ptr_2 = sip_header->sip_hdr_current;
1500 if (*sip_header->sip_hdr_current == SIP_SP) {
1501 if (sip_skip_white_space(sip_header) != 0) {
1503 * only a uri.
1505 value->cftr_uri.sip_str_ptr = tmp_ptr;
1506 value->cftr_uri.sip_str_len =
1507 tmp_ptr_2 - tmp_ptr;
1509 * It's an error not to have a uri.
1511 if (value->cftr_uri.sip_str_len == 0) {
1512 if (sip_goto_next_value(
1513 sip_header) != 0) {
1514 sip_free_cftr_header(
1515 parsed_header);
1516 return (EPROTO);
1518 value->sip_value_state =
1519 SIP_VALUE_BAD;
1520 goto get_next_cftr_value;
1522 goto get_next_cftr_value;
1526 if (*sip_header->sip_hdr_current != SIP_LAQUOT) {
1528 * No display name here.
1530 value->cftr_uri.sip_str_ptr = tmp_ptr;
1531 value->cftr_uri.sip_str_len = tmp_ptr_2 -
1532 tmp_ptr;
1534 * It's an error not to have a uri.
1536 if (value->cftr_uri.sip_str_len == 0) {
1537 if (sip_goto_next_value(sip_header) !=
1538 0) {
1539 sip_free_cftr_header(
1540 parsed_header);
1541 return (EPROTO);
1543 value->sip_value_state = SIP_VALUE_BAD;
1544 goto get_next_cftr_value;
1546 goto get_params;
1549 value->cftr_name = malloc(sizeof (sip_str_t));
1550 if (value->cftr_name == NULL) {
1551 sip_free_cftr_header(parsed_header);
1552 return (ENOMEM);
1554 value->cftr_name->sip_str_ptr = tmp_ptr;
1555 value->cftr_name->sip_str_len = tmp_ptr_2 - tmp_ptr;
1556 if (quoted_name)
1557 value->cftr_name->sip_str_len--;
1560 if (sip_find_token(sip_header, SIP_LAQUOT) != 0) {
1561 if (sip_goto_next_value(sip_header) != 0) {
1562 sip_free_cftr_header(parsed_header);
1563 return (EPROTO);
1565 value->sip_value_state = SIP_VALUE_BAD;
1566 goto get_next_cftr_value;
1569 if (*sip_header->sip_hdr_current == SIP_SP) {
1570 if (sip_skip_white_space(sip_header) != 0) {
1571 if (sip_goto_next_value(sip_header) != 0) {
1572 sip_free_cftr_header(parsed_header);
1573 return (EPROTO);
1575 value->sip_value_state = SIP_VALUE_BAD;
1576 goto get_next_cftr_value;
1580 tmp_ptr = sip_header->sip_hdr_current;
1582 if (sip_find_separator(sip_header, SIP_RAQUOT, SIP_NUL,
1583 SIP_NUL, B_FALSE)) {
1584 if (sip_goto_next_value(sip_header) != 0) {
1585 sip_free_cftr_header(parsed_header);
1586 return (EPROTO);
1588 value->sip_value_state = SIP_VALUE_BAD;
1589 goto get_next_cftr_value;
1592 value->cftr_uri.sip_str_ptr = tmp_ptr;
1593 value->cftr_uri.sip_str_len =
1594 sip_header->sip_hdr_current - tmp_ptr;
1596 if (sip_find_token(sip_header, SIP_RAQUOT) != 0) {
1597 if (sip_goto_next_value(sip_header) != 0) {
1598 sip_free_cftr_header(parsed_header);
1599 return (EINVAL);
1601 value->sip_value_state = SIP_VALUE_BAD;
1602 goto get_next_cftr_value;
1605 if (value->cftr_uri.sip_str_len <= strlen("<>")) {
1606 if (sip_goto_next_value(sip_header) != 0) {
1607 sip_free_cftr_header(parsed_header);
1608 return (EPROTO);
1610 value->sip_value_state = SIP_VALUE_BAD;
1611 goto get_next_cftr_value;
1614 get_params:
1615 ret = sip_parse_params(sip_header, &value->sip_param_list);
1616 if (ret == EPROTO) {
1617 value->sip_value_state = SIP_VALUE_BAD;
1618 } else if (ret != 0) {
1619 sip_free_cftr_header(parsed_header);
1620 return (ret);
1622 get_next_cftr_value:
1623 value->sip_value_end = sip_header->sip_hdr_current;
1626 * Parse uri
1628 if (value->cftr_uri.sip_str_len > 0) {
1629 int error;
1630 uint_t uri_errflags;
1631 char *uri = "*";
1632 _sip_msg_t *sip_msg;
1633 sip_message_type_t *msg_type;
1635 value->sip_value_parsed_uri = sip_parse_uri(
1636 &value->cftr_uri, &error);
1637 if (value->sip_value_parsed_uri == NULL) {
1638 sip_free_cftr_header(parsed_header);
1639 return (ENOMEM);
1641 uri_errflags = ((_sip_uri_t *)value->
1642 sip_value_parsed_uri)->sip_uri_errflags;
1643 if (error != 0 || uri_errflags != 0) {
1644 if ((strcmp(SIP_CONTACT, sip_header->
1645 sip_header_functions->header_name) == 0) &&
1646 (strncmp(value->cftr_uri.sip_str_ptr, uri,
1647 strlen(uri)) == 0) && (strlen(uri) ==
1648 value->cftr_uri.sip_str_len)) {
1649 sip_msg = sip_header->sip_hdr_sipmsg;
1650 msg_type = sip_msg->sip_msg_req_res;
1651 if (msg_type->is_request && msg_type->
1652 sip_req_method == REGISTER) {
1653 error = 0;
1654 ((_sip_uri_t *)value->
1655 sip_value_parsed_uri)->
1656 sip_uri_errflags = 0;
1657 } else {
1658 value->sip_value_state =
1659 SIP_VALUE_BAD;
1661 } else {
1662 value->sip_value_state = SIP_VALUE_BAD;
1667 (void) sip_find_token(sip_header, SIP_COMMA);
1668 last_value = value;
1669 (void) sip_skip_white_space(sip_header);
1672 sip_header->sip_hdr_parsed = parsed_header;
1674 *header = parsed_header;
1675 return (0);
1679 * PAssertedID = "P-Asserted-Identity" HCOLON PAssertedID-value
1680 * *(COMMA PAssertedID-value)
1681 * PAssertedID-value = name-addr / addr-spec
1684 sip_parse_passertedid(_sip_header_t *sip_header, sip_parsed_header_t **header)
1686 return (sip_parse_hdr_parser3(sip_header, header, SIP_STRS_VAL,
1687 B_TRUE));
1691 * PPreferredID = "P-Preferred-Identity" HCOLON PPreferredID-value
1692 * *(COMMA PAssertedID-value)
1693 * PPreferredID-value = name-addr / addr-spec
1696 sip_parse_ppreferredid(_sip_header_t *sip_header, sip_parsed_header_t **header)
1698 return (sip_parse_hdr_parser3(sip_header, header, SIP_STRS_VAL,
1699 B_TRUE));
1704 * We don't do anything for a header we don't understand
1706 /* ARGSUSED */
1708 sip_parse_unknown_header(_sip_header_t *sip_header,
1709 sip_parsed_header_t **header)
1711 return (EINVAL);