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]
23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
32 #include "sip_parse_uri.h"
35 * SIP-URI = "sip:" [ userinfo ] hostport uri-parameters [ headers ]
36 * SIPS-URI = "sips:" [ userinfo ] hostport uri-parameters [ headers ]
37 * userinfo = ( user / telephone-subscriber ) [ ":" password ] "@"
38 * user = 1*( unreserved / escaped / user-unreserved )
39 * user-unreserved = "&" / "=" / "+" / "$" / "," / ";" / "?" / "/"
40 * password = *( unreserved / escaped / "&" / "=" / "+" / "$" / "," )
41 * hostport = host [ ":" port ]
42 * host = hostname / IPv4address / IPv6reference
43 * hostname = *( domainlabel "." ) toplabel [ "." ]
44 * domainlabel = alphanum / alphanum *( alphanum / "-" ) alphanum
45 * toplabel = ALPHA / ALPHA *( alphanum / "-" ) alphanum
46 * IPv4address = 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT
47 * IPv6reference = "[" IPv6address "]"
48 * IPv6address = hexpart [ ":" IPv4address ]
49 * hexpart = hexseq / hexseq "::" [ hexseq ] / "::" [ hexseq ]
50 * hexseq = hex4 *( ":" hex4)
54 * The BNF for telephone-subscriber can be found in RFC 2806 [9]. Note,
55 * however, that any characters allowed there that are not allowed in
56 * the user part of the SIP URI MUST be escaped.
58 * uri-parameters = *( ";" uri-parameter)
59 * uri-parameter = transport-param / user-param / method-param
60 * / ttl-param / maddr-param / lr-param / other-param
61 * transport-param = "transport="( "udp" / "tcp" / "sctp" / "tls"
63 * other-transport = token
64 * user-param = "user=" ( "phone" / "ip" / other-user)
66 * method-param = "method=" Method
67 * ttl-param = "ttl=" ttl
68 * maddr-param = "maddr=" host
70 * other-param = pname [ "=" pvalue ]
72 * pvalue = 1*paramchar
73 * paramchar = param-unreserved / unreserved / escaped
74 * param-unreserved = "[" / "]" / "/" / ":" / "&" / "+" / "$"
75 * headers = "?" header *( "&" header )
76 * header = hname "=" hvalue
77 * hname = 1*( hnv-unreserved / unreserved / escaped )
78 * hvalue = *( hnv-unreserved / unreserved / escaped )
79 * hnv-unreserved = "[" / "]" / "/" / "?" / ":" / "+" / "$"
83 #define SIP_URI_MSG_BUF_SZ 100
85 #define SIP_URI_ISHEX(c) \
86 (((int)(c) >= 0x30 && (int)(c) <= 0x39) || \
87 ((int)(c) >= 0x41 && (int)(c) <= 0x46) || \
88 ((int)(c) >= 0x61 && (int)(c) <= 0x66))
90 #define SIP_URI_ISURLESCAPE(scan, end) \
91 ((scan) + 2 < (end) && (scan)[0] == '%' && \
92 SIP_URI_ISHEX((scan)[1]) && SIP_URI_ISHEX((scan[2])))
95 * URL character classes
96 * mark - _ . ! ~ * ' ()
97 * reserved ; / ? : @ & = + $ , also [] for IPv6
98 * unreserved alphanum mark
99 * pchar : @ & = + $ , unreserved
100 * userinfo ; : & = + $ , unreserved escaped
101 * relsegment ; @ & = + $ , unreserved escaped
102 * reg_name ; : @ & = + $ , unreserved escaped
103 * token - _ . ! ~ * ' % + `
104 * param-unreserved [ ] / : + $ &
105 * hnv-unreserved [ ] / : + $ ?
107 #define SIP_URI_ALPHA_BIT 0x0001
108 #define SIP_URI_DIGIT_BIT 0x0002
109 #define SIP_URI_ALNUM_BITS 0x0003
110 #define SIP_URI_SCHEME_BIT 0x0004 /* for - + . */
111 #define SIP_URI_TOKEN_BIT 0x0008 /* for - _ . ! ~ * ' % + ` */
112 #define SIP_URI_QUEST_BIT 0x0010 /* for ? */
113 #define SIP_URI_AT_BIT 0x0020 /* for @ */
114 #define SIP_URI_COLON_BIT 0x0040 /* for : */
115 #define SIP_URI_SEMI_BIT 0x0080 /* for ; */
116 #define SIP_URI_DASH_BIT 0x0100 /* for - */
117 #define SIP_URI_MARK_BIT 0x0200 /* for - _ . ! ~ * ' ( ) */
118 #define SIP_URI_AND_BIT 0x0400 /* for & */
119 #define SIP_URI_PHCOMM_BIT 0x0800 /* for [ ] / : + $ */
120 #define SIP_URI_OTHER_BIT 0x1000 /* for = + $ , */
121 #define SIP_URI_SLASH_BIT 0x2000 /* for / */
122 #define SIP_URI_VISUALSEP_BIT 0x4000 /* for -.() */
123 #define SIP_URI_DTMFURI_DIGIT_BIT 0x8000 /* for *ABCD */
125 #define a SIP_URI_ALPHA_BIT
126 #define d SIP_URI_DIGIT_BIT
127 #define s SIP_URI_SCHEME_BIT
128 #define t SIP_URI_TOKEN_BIT
129 #define q SIP_URI_QUEST_BIT
130 #define m SIP_URI_AT_BIT
131 #define c SIP_URI_COLON_BIT
132 #define i SIP_URI_SEMI_BIT
133 #define h SIP_URI_DASH_BIT
134 #define k SIP_URI_MARK_BIT
135 #define n SIP_URI_AND_BIT
136 #define o SIP_URI_PHCOMM_BIT
137 #define r SIP_URI_OTHER_BIT
138 #define l SIP_URI_SLASH_BIT
139 #define v SIP_URI_VISUALSEP_BIT
140 #define f SIP_URI_DTMFURI_DIGIT_BIT
142 static const unsigned short sip_uri_table
[256] = {
143 0, 0, 0, 0, 0, 0, 0, 0,
144 0, 0, 0, 0, 0, 0, 0, 0,
145 0, 0, 0, 0, 0, 0, 0, 0,
146 0, 0, 0, 0, 0, 0, 0, 0,
147 0, t
|k
, 0, 0, o
|r
, t
, n
, t
|k
,
148 k
|v
, k
|v
, t
|k
|f
, s
|t
|r
|o
, r
, h
|s
|t
|k
|v
, s
|t
|k
|v
, o
|l
,
149 d
, d
, d
, d
, d
, d
, d
, d
,
150 d
, d
, c
|o
, i
, 0, r
, 0, q
,
151 m
, a
|f
, a
|f
, a
|f
, a
|f
, a
, a
, a
,
152 a
, a
, a
, a
, a
, a
, a
, a
,
153 a
, a
, a
, a
, a
, a
, a
, a
,
154 a
, a
, a
, o
, 0, o
, 0, t
|k
,
155 t
, a
, a
, a
, a
, a
, a
, a
,
156 a
, a
, a
, a
, a
, a
, a
, a
,
157 a
, a
, a
, a
, a
, a
, a
, a
,
158 a
, a
, a
, 0, 0, 0, t
|k
, 0,
159 0, 0, 0, 0, 0, 0, 0, 0,
160 0, 0, 0, 0, 0, 0, 0, 0,
161 0, 0, 0, 0, 0, 0, 0, 0,
162 0, 0, 0, 0, 0, 0, 0, 0,
163 0, 0, 0, 0, 0, 0, 0, 0,
164 0, 0, 0, 0, 0, 0, 0, 0,
165 0, 0, 0, 0, 0, 0, 0, 0,
166 0, 0, 0, 0, 0, 0, 0, 0,
167 0, 0, 0, 0, 0, 0, 0, 0,
168 0, 0, 0, 0, 0, 0, 0, 0,
169 0, 0, 0, 0, 0, 0, 0, 0,
170 0, 0, 0, 0, 0, 0, 0, 0,
171 0, 0, 0, 0, 0, 0, 0, 0,
172 0, 0, 0, 0, 0, 0, 0, 0,
173 0, 0, 0, 0, 0, 0, 0, 0,
174 0, 0, 0, 0, 0, 0, 0, 0,
194 #define SIP_URI_UT(c) sip_uri_table[(unsigned char)(c)]
195 #define SIP_URI_ISALPHA(c) (SIP_URI_UT(c) & SIP_URI_ALPHA_BIT)
196 #define SIP_URI_ISDIGIT(c) (SIP_URI_UT(c) & SIP_URI_DIGIT_BIT)
197 #define SIP_URI_ISALNUM(c) (SIP_URI_UT(c) & SIP_URI_ALNUM_BITS)
198 #define SIP_URI_ISSCHEME(c) \
199 (SIP_URI_UT(c) & (SIP_URI_ALNUM_BITS|SIP_URI_SCHEME_BIT))
200 #define SIP_URI_ISTOKEN(c) \
201 (SIP_URI_UT(c) & (SIP_URI_ALNUM_BITS|SIP_URI_TOKEN_BIT))
202 #define SIP_URI_ISSIPDELIM(c) \
203 (SIP_URI_UT(c) & (SIP_URI_SEMI_BIT|SIP_URI_QUEST_BIT))
204 #define SIP_URI_ISSIPHDELIM(c) \
205 (SIP_URI_UT(c) & (SIP_URI_COLON_BIT|SIP_URI_SEMI_BIT|SIP_URI_QUEST_BIT))
206 #define SIP_URI_ISHOST(c) \
207 (SIP_URI_UT(c) & (SIP_URI_ALNUM_BITS|SIP_URI_DASH_BIT))
208 #define SIP_URI_ISUSER(c) \
209 (SIP_URI_UT(c) & (SIP_URI_OTHER_BIT|SIP_URI_SEMI_BIT| \
210 SIP_URI_QUEST_BIT|SIP_URI_SLASH_BIT|SIP_URI_AND_BIT))
212 #define SIP_URI_ISABSHDELIM(c) \
214 (SIP_URI_SLASH_BIT|SIP_URI_COLON_BIT|SIP_URI_QUEST_BIT))
215 #define SIP_URI_ISABSDELIM(c) \
216 (SIP_URI_UT(c) & (SIP_URI_SLASH_BIT|SIP_URI_QUEST_BIT))
217 #define SIP_URI_ISUNRESERVED(c) \
218 (SIP_URI_UT(c) & (SIP_URI_ALNUM_BITS|SIP_URI_MARK_BIT))
219 #define SIP_URI_ISPARAM(c) \
220 (SIP_URI_UT(c) & (SIP_URI_PHCOMM_BIT|SIP_URI_AND_BIT|\
221 SIP_URI_ALNUM_BITS|SIP_URI_MARK_BIT))
222 #define SIP_URI_ISHEADER(c) \
223 (SIP_URI_UT(c) & (SIP_URI_PHCOMM_BIT|SIP_URI_QUEST_BIT|\
224 SIP_URI_ALNUM_BITS|SIP_URI_MARK_BIT))
225 #define SIP_URI_ISOTHER(c) (SIP_URI_UT(c) & SIP_URI_OTHER_BIT)
226 #define SIP_URI_ISRESERVED(c) \
227 (SIP_URI_UT(c) & (SIP_URI_SEMI_BIT|SIP_URI_SLASH_BIT| \
228 SIP_URI_QUEST_BIT| SIP_URI_COLON_BIT|SIP_URI_AT_BIT| \
229 SIP_URI_AND_BIT|SIP_URI_OTHER_BIT))
230 #define SIP_URI_ISPCHAR(c) \
231 (SIP_URI_UT(c) & (SIP_URI_COLON_BIT|SIP_URI_AT_BIT| \
232 SIP_URI_AND_BIT|SIP_URI_OTHER_BIT))
233 #define SIP_URI_ISREGNAME(c) \
235 (SIP_URI_OTHER_BIT|SIP_URI_SEMI_BIT|SIP_URI_COLON_BIT| \
236 SIP_URI_AT_BIT|SIP_URI_AND_BIT))
237 #define SIP_URI_ISPHONEDIGIT(c) \
238 (SIP_URI_UT(c) & (SIP_URI_DIGIT_BIT|SIP_URI_VISUALSEP_BIT))
239 #define SIP_URI_ISDTMFDIGIT(c) (SIP_URI_UT(c) & SIP_URI_DTMFURI_DIGIT_BIT)
241 static int sip_uri_url_casecmp(const char *, const char *, unsigned);
242 static void sip_uri_parse_params(_sip_uri_t
*, char *, char *);
243 static void sip_uri_parse_headers(_sip_uri_t
*, char *, char *);
244 static void sip_uri_parse_abs_opaque(_sip_uri_t
*, char *, char *);
245 static void sip_uri_parse_abs_query(_sip_uri_t
*, char *, char *);
246 static void sip_uri_parse_abs_path(_sip_uri_t
*, char *, char *);
247 static void sip_uri_parse_abs_regname(_sip_uri_t
*, char *, char *);
248 static int sip_uri_parse_scheme(_sip_uri_t
*, char *, char *);
249 static void sip_uri_parse_password(_sip_uri_t
*, char *, char *);
250 static void sip_uri_parse_user(_sip_uri_t
*, char *, char *);
251 static void sip_uri_parse_port(_sip_uri_t
*, char *, char *);
252 static void sip_uri_parse_netpath(_sip_uri_t
*, char **, char *, boolean_t
);
253 static int sip_uri_parse_ipv6(char *, char *);
254 static int sip_uri_parse_ipv4(char *, char *);
255 static int sip_uri_parse_hostname(char *, char *);
256 static int sip_uri_parse_tel(char *, char *);
257 static int sip_uri_parse_tel_areaspe(char *, char *);
258 static int sip_uri_parse_tel_servicepro(char *, char *);
259 static int sip_uri_parse_tel_futureext(char *, char *);
260 static int sip_uri_isTokenchar(char **, char *);
261 static int sip_uri_isEscapedPound(char **, char *);
262 static int sip_uri_hexVal(char *, char *);
263 static int SIP_URI_HEXVAL(int);
266 * get the hex value of a char
269 SIP_URI_HEXVAL(int c
)
271 if (c
>= 0x30 && c
<= 0x39)
273 if (c
>= 0x41 && c
<= 0x46)
274 return (c
- 'A' + 10);
275 if (c
>= 0x61 && c
<= 0x66)
276 return (c
- 'a' + 10);
281 * basic ASCII case-insensitive comparison
284 sip_uri_url_casecmp(const char *str1
, const char *str2
, unsigned len
)
288 for (j
= 0; j
< len
&& tolower(str1
[j
]) == tolower(str2
[j
]) &&
289 str1
[j
] != '\0'; ++j
) {
292 return (j
== len
? 0 : tolower(str2
[j
]) - tolower(str1
[j
]));
296 * telephone-subscriber = global-phone-number / local-phone-number
297 * Please refer to RFC 2806
300 sip_uri_parse_tel(char *scan
, char *uend
)
315 while (scan
< uend
&& SIP_URI_ISPHONEDIGIT(*scan
))
318 while (scan
< uend
&&
319 (SIP_URI_ISPHONEDIGIT(*scan
) ||
320 SIP_URI_ISDTMFDIGIT(*scan
) ||
321 sip_uri_isEscapedPound(&scan
, uend
) ||
322 *scan
== 'p' || *scan
== 'w')) {
326 if (mark
== scan
|| (scan
< uend
&& *scan
!= ';'))
330 * parse isdn-subaddress
332 if (uend
- scan
> 6 && !sip_uri_url_casecmp(scan
, ";isub=", 6)) {
335 while (scan
< uend
&& SIP_URI_ISPHONEDIGIT(*scan
))
337 if (mark
== scan
|| (scan
< uend
&& *scan
!= ';'))
344 if (uend
- scan
> 7 && !sip_uri_url_casecmp(scan
, ";postd=", 7)) {
347 while (scan
< uend
&&
348 (SIP_URI_ISPHONEDIGIT(*scan
) ||
349 SIP_URI_ISDTMFDIGIT(*scan
) ||
350 sip_uri_isEscapedPound(&scan
, uend
) ||
351 *scan
== 'p' || *scan
== 'w')) {
354 if (mark
== scan
|| (scan
< uend
&& *scan
!= ';'))
360 * parse area-specifier
362 if (uend
- scan
> 15 &&
363 !sip_uri_url_casecmp(scan
, ";phone-context=", 15)) {
366 while (scan
< uend
&& *scan
!= ';')
368 ret
= sip_uri_parse_tel_areaspe(mark
, scan
);
375 * parse area-specifier, service-provider, future-extension
377 while (scan
< uend
&& ret
) {
378 if (uend
- scan
> 15 &&
379 !sip_uri_url_casecmp(scan
, ";phone-context=", 15)) {
382 while (scan
< uend
&& *scan
!= ';')
384 ret
= sip_uri_parse_tel_areaspe(mark
, scan
);
385 } else if (uend
- scan
> 5 &&
386 !sip_uri_url_casecmp(scan
, ";tsp=", 5)) {
389 while (scan
< uend
&& *scan
!= ';')
391 ret
= sip_uri_parse_tel_servicepro(mark
, scan
);
395 while (scan
< uend
&& (*scan
!= ';' || quote
)) {
396 if (sip_uri_hexVal(scan
, uend
) == 0x22) {
403 ret
= sip_uri_parse_tel_futureext(mark
, scan
);
406 return (ret
&& scan
== uend
);
410 * area-specifier = ";" phone-context-tag "=" phone-context-ident
411 * phone-context-tag = "phone-context"
412 * phone-context-ident = network-prefix / private-prefix
413 * network-prefix = global-network-prefix / local-network-prefix
414 * global-network-prefix = "+" 1*phonedigit
415 * local-network-prefix = 1*(phonedigit / dtmf-digit / pause-character)
416 * private-prefix = (%x21-22 / %x24-27 / %x2C / %x2F / %x3A /
417 * %x3C-40 / %x45-4F / %x51-56 / %x58-60 /
418 * %x65-6F / %x71-76 / %x78-7E)
419 * *(%x21-3A / %x3C-7E)
420 * phonedigit = DIGIT / visual-separator
421 * visual-separator = "-" / "." / "(" / ")"
422 * pause-character = one-second-pause / wait-for-dial-tone
423 * one-second-pause = "p"
424 * wait-for-dial-tone = "w"
425 * dtmf-digit = "*" / "#" / "A" / "B" / "C" / "D"
428 sip_uri_parse_tel_areaspe(char *scan
, char *uend
)
436 * parse global-network-prefix
442 while (scan
< uend
&& SIP_URI_ISPHONEDIGIT(*scan
))
445 * parse local-network-prefix
447 } else if (SIP_URI_ISPHONEDIGIT(*scan
) || SIP_URI_ISDTMFDIGIT(*scan
) ||
448 sip_uri_isEscapedPound(&scan
, uend
) ||
449 *scan
== 'p' || *scan
== 'w') {
451 while (scan
< uend
&&
452 (SIP_URI_ISPHONEDIGIT(*scan
) ||
453 SIP_URI_ISDTMFDIGIT(*scan
) ||
454 sip_uri_isEscapedPound(&scan
, uend
) ||
455 *scan
== 'p' || *scan
== 'w')) {
460 * parse private-prefix
462 * any characters allowed in RFC 2806 that are not allowed in
463 * the user part of the SIP URI MUST be escaped
465 * private-prefix = (! $ & ', / = ? _
466 * EFGHIJKLMNOQRSTUVXYZ efghijklmnoqrstuvxyz
467 * { } | ~ [ ] \ ^ ` " % : < > @)
468 * *(%x21-3A / %x3C-7E)
470 * following characters are allowed in RFC 2806 and
471 * the user part of SIP URI
472 * ! $ & ', / = ? _ EFGHIJKLMNOQRSTUVXYZ efghijklmnoqrstuvxyz
474 if (*scan
== '!' || *scan
== '$' || *scan
== '&' ||
475 *scan
== '\'' || *scan
== ',' || *scan
== '/' ||
476 *scan
== '=' || *scan
== '?' || *scan
== '_' ||
477 (*scan
>= 'E' && *scan
<= 'Z' &&
478 *scan
!= 'P' && *scan
!= 'W') ||
479 (*scan
>= 'e' && *scan
<= 'z' &&
480 *scan
!= 'p' && *scan
!= 'w')) {
483 uri_hexValue
= sip_uri_hexVal(scan
, uend
);
484 if (uri_hexValue
== 0x21 || uri_hexValue
== 0x22 ||
485 (uri_hexValue
>= 0x24 && uri_hexValue
<= 0x27) ||
486 uri_hexValue
== 0x2c || uri_hexValue
== 0x2f ||
487 uri_hexValue
== 0x3a ||
488 (uri_hexValue
>= 0x3c && uri_hexValue
<= 0x40) ||
489 (uri_hexValue
>= 0x45 && uri_hexValue
<= 0x4f) ||
490 (uri_hexValue
>= 0x51 && uri_hexValue
<= 0x56) ||
491 (uri_hexValue
>= 0x58 && uri_hexValue
<= 0x60) ||
492 (uri_hexValue
>= 0x65 && uri_hexValue
<= 0x6f) ||
493 (uri_hexValue
>= 0x71 && uri_hexValue
<= 0x76) ||
494 (uri_hexValue
>= 0x78 && uri_hexValue
<= 0x7e)) {
501 * parse *(%x21-3A / %x3C-7E)
503 while (scan
< uend
) {
504 if (SIP_URI_ISUNRESERVED(*scan
) ||
505 (SIP_URI_ISUSER(*scan
) && *scan
!= ';')) {
508 uri_hexValue
= sip_uri_hexVal(scan
, uend
);
509 if (uri_hexValue
>= 0x21 &&
510 uri_hexValue
<= 0x7e &&
511 uri_hexValue
!= 0x3b) {
525 sip_uri_hexVal(char *scan
, char *uend
)
529 if (SIP_URI_ISURLESCAPE(scan
, uend
)) {
530 ret
= (SIP_URI_ISDIGIT(scan
[1]) ? (scan
[1] - '0') :
531 (tolower(scan
[1]) - 'a' + 10)) * 16 +
532 (SIP_URI_ISDIGIT(scan
[2]) ? (scan
[2] - '0') :
533 (tolower(scan
[2]) - 'a' + 10));
539 * service-provider = ";" provider-tag "=" provider-hostname
540 * provider-tag = "tsp"
541 * provider-hostname = domain
544 sip_uri_parse_tel_servicepro(char *scan
, char *uend
)
554 if (sip_uri_hexVal(scan
, uend
) == 0x20 && scan
+ 3 == uend
)
556 while (scan
< uend
) {
558 while (scan
< uend
&& (*scan
== '-'|| SIP_URI_ISALNUM(*scan
)))
560 if ((scan
< uend
&& *scan
!= '.') ||
561 !SIP_URI_ISALPHA(*mark
) || !SIP_URI_ISALNUM(*(scan
- 1))) {
574 * future-extension = ";" 1*(token-char) ["=" ((1*(token-char)
575 * ["?" 1*(token-char)]) / quoted-string )]
576 * token-char = (%x21 / %x23-27 / %x2A-2B / %x2D-2E / %x30-39
577 * / %x41-5A / %x5E-7A / %x7C / %x7E)
580 sip_uri_parse_tel_futureext(char *scan
, char *uend
)
583 int uri_hexValue
= 0;
589 * parse 1*(token-char)
592 while (scan
< uend
&& sip_uri_isTokenchar(&scan
, uend
))
595 (scan
< uend
&& (*scan
!= '=' || scan
+ 1 == uend
))) {
603 * parse 1*token-char ["?" 1*token-char]
605 if (sip_uri_isTokenchar(&scan
, uend
)) {
606 while (sip_uri_isTokenchar(&scan
, uend
))
613 while (sip_uri_isTokenchar(&scan
, uend
))
618 } else { /* parse quoted-string */
619 uri_hexValue
= sip_uri_hexVal(scan
, uend
);
620 if (uri_hexValue
!= 0x22)
623 while (scan
< uend
&& sip_uri_hexVal(scan
, uend
) != 0x22) {
627 if (sip_uri_hexVal(scan
, uend
) == 0x5c) {
630 if (SIP_URI_ISUNRESERVED(*scan
) ||
631 SIP_URI_ISUSER(*scan
)) {
633 } else if (sip_uri_hexVal(scan
, uend
) >=
635 sip_uri_hexVal(scan
, uend
) <=
645 if (SIP_URI_ISUNRESERVED(*scan
) ||
646 SIP_URI_ISUSER(*scan
)) {
650 sip_uri_hexVal(scan
, uend
);
651 if ((uri_hexValue
>= 0x20 &&
652 uri_hexValue
<= 0x21) ||
653 (uri_hexValue
>= 0x23 &&
654 uri_hexValue
<= 0x7e) ||
655 (uri_hexValue
>= 0x80 &&
656 uri_hexValue
<= 0xff)) {
665 (scan
< uend
&& sip_uri_hexVal(scan
, uend
) != 0x22)) {
677 * Any characters allowed in RFC2806 tel URL that are not allowed in
678 * the user part of the SIP URI MUST be escaped.
679 * token-char = - _ . ! ~ * ' $ & + DIGIT ALPHA # % ^ ` |
682 sip_uri_isTokenchar(char **pscan
, char *uend
)
685 int uri_hexValue
= 0;
691 * for ALPAH DIGIT - _ . ! ~ * ' $ & +
693 if ((SIP_URI_ISUNRESERVED(*scan
) && *scan
!= '(' && *scan
!= ')') ||
694 *scan
== '$' || *scan
== '&' || *scan
== '+') {
700 uri_hexValue
= sip_uri_hexVal(scan
, uend
);
701 if (uri_hexValue
== 0x21 || uri_hexValue
== 0x7c ||
702 uri_hexValue
== 0x7e ||
703 (uri_hexValue
>= 0x23 && uri_hexValue
<= 0x27) ||
704 (uri_hexValue
>= 0x2a && uri_hexValue
<= 0x2b) ||
705 (uri_hexValue
>= 0x2d && uri_hexValue
<= 0x2e) ||
706 (uri_hexValue
>= 0x30 && uri_hexValue
<= 0x39) ||
707 (uri_hexValue
>= 0x41 && uri_hexValue
<= 0x5a) ||
708 (uri_hexValue
>= 0x5e && uri_hexValue
<= 0x7a)) {
717 * '#' is not allowed in the telephone-subscriber part of SIP URI
721 sip_uri_isEscapedPound(char **pscan
, char *uend
)
727 if (*scan
== '%' && scan
+ 2 < uend
&& scan
[1] == '2' &&
737 * scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
740 sip_uri_parse_scheme(_sip_uri_t
*outurl
, char *scan
, char *uend
)
743 outurl
->sip_uri_errflags
|= SIP_URIERR_SCHEME
;
746 outurl
->sip_uri_scheme
.sip_str_ptr
= scan
;
747 outurl
->sip_uri_scheme
.sip_str_len
= uend
- scan
;
749 if (scan
< uend
&& SIP_URI_ISALPHA(*scan
)) {
751 while (scan
< uend
&& SIP_URI_ISSCHEME(*scan
))
755 outurl
->sip_uri_errflags
|= SIP_URIERR_SCHEME
;
760 * The format of params is supposed to be;XXX;XXX;XXX
761 * uri-parameters = *(";" uri-parameter)
762 * uri-parameter = transport-param / user-param / method-param
763 * / ttl-param / maddr-param / lr-param / other-param
764 * transport-param = "transport="
765 * ("udp" / "tcp" / "sctp" / "tls" / other-transport)
766 * other-transport = token
767 * user-param = "user=" ("phone" / "ip" / other-user)
769 * method-param = "method=" Method
770 * ttl-param = "ttl=" ttl
771 * maddr-param = "maddr=" host
773 * other-param = pname [ "=" pvalue ]
774 * pname = 1*paramchar
775 * pvalue = 1*paramchar
776 * paramchar = param-unreserved / unreserved / escaped
777 * param-unreserved = "[" / "]" / "/" / ":" / "&" / "+" / "$"
780 sip_uri_parse_params(_sip_uri_t
*outurl
, char *scan
, char *uend
)
786 int paramleftlen
= 0;
788 sip_param_t
*param
= NULL
;
789 sip_param_t
*new_param
= NULL
;
791 if (scan
== uend
|| *scan
!= ';' || scan
+ 1 == uend
) {
792 outurl
->sip_uri_errflags
|= SIP_URIERR_PARAM
;
796 while (scan
< uend
) {
798 while (scan
< uend
&& *scan
!= ';')
801 outurl
->sip_uri_errflags
|= SIP_URIERR_PARAM
;
805 new_param
= calloc(1, sizeof (sip_param_t
));
806 if (new_param
== NULL
) {
807 outurl
->sip_uri_errflags
|= SIP_URIERR_MEMORY
;
812 outurl
->sip_uri_params
= new_param
;
814 param
->param_next
= new_param
;
818 param
->param_name
.sip_str_ptr
= mark
;
819 equal
= memchr(mark
, '=', scan
- mark
);
821 param
->param_name
.sip_str_len
= scan
- mark
;
822 param
->param_value
.sip_str_ptr
= NULL
;
823 param
->param_value
.sip_str_len
= 0;
824 while (mark
< scan
&& (SIP_URI_ISPARAM(*mark
) ||
825 SIP_URI_ISURLESCAPE(mark
, scan
))) {
829 param
->param_name
.sip_str_len
= equal
- mark
;
830 param
->param_value
.sip_str_ptr
= equal
+ 1;
831 param
->param_value
.sip_str_len
= scan
- equal
- 1;
833 if (mark
== equal
|| equal
+ 1 == scan
) {
834 outurl
->sip_uri_errflags
|= SIP_URIERR_PARAM
;
837 paramleftlen
= equal
- mark
+ 1;
838 if ((paramleftlen
== 10 &&
839 !sip_uri_url_casecmp(mark
, "transport=", 10)) ||
840 (paramleftlen
== 5 &&
841 !sip_uri_url_casecmp(mark
, "user=", 5)) ||
842 (paramleftlen
== 7 &&
843 !sip_uri_url_casecmp(mark
, "method=", 7))) {
844 if (scan
- equal
== 1) {
845 outurl
->sip_uri_errflags
|=
850 while (mark
< scan
&& SIP_URI_ISTOKEN(*mark
))
852 } else if (paramleftlen
== 4 &&
853 !sip_uri_url_casecmp(mark
, "ttl=", 4)) {
854 if (scan
- equal
== 1) {
855 outurl
->sip_uri_errflags
|=
860 for (i
= 0; i
< 3; ++i
) {
863 SIP_URI_ISDIGIT(*mark
)) {
864 ttl
= ttl
* 10 + (*mark
- '0');
867 outurl
->sip_uri_errflags
|=
872 } else if (paramleftlen
== 6 &&
873 !sip_uri_url_casecmp(mark
, "maddr=", 6)) {
876 if (mark
< scan
&& SIP_URI_ISDIGIT(*mark
)) {
877 gothost
= sip_uri_parse_ipv4(mark
,
881 * not valid syntax for a host or user name,
884 if (!gothost
&& mark
< scan
&& *mark
== '[') {
885 gothost
= sip_uri_parse_ipv6(mark
,
889 * look for a valid host name:
890 * *(domainlabel ".") toplabel ["."]
892 if (!gothost
&& mark
< scan
) {
894 sip_uri_parse_hostname(mark
,
896 outurl
->sip_uri_errflags
|=
902 } else if (paramleftlen
== 3 &&
903 !sip_uri_url_casecmp(mark
, "lr=", 3)) {
904 outurl
->sip_uri_errflags
|= SIP_URIERR_PARAM
;
907 while (mark
< scan
&& (SIP_URI_ISPARAM(*mark
) ||
908 SIP_URI_ISURLESCAPE(mark
, scan
) ||
915 outurl
->sip_uri_errflags
|= SIP_URIERR_PARAM
;
922 * The format of headers is supposed to be ?XXX&XXX&XXX
923 * headers = "?" header *("&" header
924 * header = hname "=" hvalue
925 * hname = 1*(hnv-unreserved / unreserved / escaped
926 * hvalue = *(hnv-unreserved / unreserved / escaped
927 * hnv-unreserved = "[" / "]" / "/" / "?" / ":" / "+" / "$"
930 sip_uri_parse_headers(_sip_uri_t
*outurl
, char *scan
, char *uend
)
935 if (scan
== uend
|| *scan
!= '?' || scan
+ 1 == uend
) {
936 outurl
->sip_uri_errflags
|= SIP_URIERR_HEADER
;
939 outurl
->sip_uri_headers
.sip_str_ptr
= scan
+ 1;
940 outurl
->sip_uri_headers
.sip_str_len
= uend
- (scan
+ 1);
942 while (scan
< uend
) {
944 while (scan
< uend
&& *scan
!= '&')
947 outurl
->sip_uri_errflags
|= SIP_URIERR_HEADER
;
950 equal
= memchr(mark
, '=', scan
- mark
);
951 if (equal
== mark
|| equal
== NULL
) {
952 outurl
->sip_uri_errflags
|= SIP_URIERR_HEADER
;
955 while (mark
< scan
&&
956 (SIP_URI_ISHEADER(*mark
) ||
957 SIP_URI_ISURLESCAPE(mark
, scan
) || mark
== equal
)) {
961 outurl
->sip_uri_errflags
|= SIP_URIERR_HEADER
;
968 * opaque-part = uric-no-slash *uric
969 * uric = reserved / unreserved / escaped
970 * uric-no-slash = unreserved / escaped / ";" / "?" / ":" / "@"
971 * / "&" / "=" / "+" / "$" / ","
974 sip_uri_parse_abs_opaque(_sip_uri_t
*outurl
, char *scan
, char *uend
)
977 outurl
->sip_uri_errflags
|= SIP_URIERR_OPAQUE
;
980 outurl
->sip_uri_opaque
.sip_str_ptr
= scan
;
981 outurl
->sip_uri_opaque
.sip_str_len
= uend
- scan
;
983 if (SIP_URI_ISUNRESERVED(*scan
) || SIP_URI_ISURLESCAPE(scan
, uend
) ||
984 SIP_URI_ISOTHER(*scan
) || *scan
== ';' || *scan
== '?' ||
985 *scan
== ':' || *scan
== '@' || *scan
== '&') {
988 outurl
->sip_uri_errflags
|= SIP_URIERR_OPAQUE
;
991 while (scan
< uend
&& (SIP_URI_ISRESERVED(*scan
) ||
992 SIP_URI_ISUNRESERVED(*scan
) || SIP_URI_ISURLESCAPE(scan
, uend
))) {
996 outurl
->sip_uri_errflags
|= SIP_URIERR_OPAQUE
;
1000 * format of query is supposed to be ?XXX
1002 * uric = reserved / unreserved / escaped
1005 sip_uri_parse_abs_query(_sip_uri_t
*outurl
, char *scan
, char *uend
)
1007 if (uend
== scan
|| *scan
!= '?' || scan
+ 1 == uend
)
1010 outurl
->sip_uri_query
.sip_str_ptr
= scan
;
1011 outurl
->sip_uri_query
.sip_str_len
= uend
- scan
;
1013 while (scan
< uend
&& (SIP_URI_ISRESERVED(*scan
) ||
1014 SIP_URI_ISUNRESERVED(*scan
) || SIP_URI_ISURLESCAPE(scan
, uend
))) {
1018 outurl
->sip_uri_errflags
|= SIP_URIERR_QUERY
;
1022 * the format of path is supposed to be /XXX;XXX/XXX;
1023 * abs-path = "/" path-segments
1024 * path-segments = segment *( "/" segment )
1025 * segment = *pchar *( ";" param )
1027 * pchar = unreserved / escaped /
1028 * ":" / "@" / "&" / "=" / "+" / "$" / ","
1031 sip_uri_parse_abs_path(_sip_uri_t
*outurl
, char *scan
, char *uend
)
1033 if (scan
== uend
|| *scan
!= '/')
1035 outurl
->sip_uri_path
.sip_str_ptr
= scan
;
1036 outurl
->sip_uri_path
.sip_str_len
= uend
- scan
;
1039 while (scan
< uend
&& (SIP_URI_ISPCHAR(*scan
) ||
1040 SIP_URI_ISUNRESERVED(*scan
) || SIP_URI_ISURLESCAPE(scan
, uend
) ||
1041 *scan
== '/' || *scan
== ';')) {
1045 outurl
->sip_uri_errflags
|= SIP_URIERR_PATH
;
1048 * reg-name = 1*( unreserved / escaped / "$" / "," / ";"
1049 * / ":" / "@" / "&" / "=" / "+" )
1052 sip_uri_parse_abs_regname(_sip_uri_t
*outurl
, char *scan
, char *uend
)
1056 outurl
->sip_uri_regname
.sip_str_ptr
= scan
;
1057 outurl
->sip_uri_regname
.sip_str_len
= uend
- scan
;
1059 while (scan
< uend
&& (SIP_URI_ISUNRESERVED(*scan
) ||
1060 SIP_URI_ISURLESCAPE(scan
, uend
) || SIP_URI_ISREGNAME(*scan
))) {
1064 outurl
->sip_uri_errflags
|= SIP_URIERR_REGNAME
;
1068 * The format of the password is supposed to be :XXX
1069 * password = *( unreserved / escaped / "&" / "=" / "+" / "$" / "," )
1072 sip_uri_parse_password(_sip_uri_t
*outurl
, char *scan
, char *uend
)
1074 if (scan
== uend
|| *scan
!= ':' || scan
+ 1 == uend
)
1077 outurl
->sip_uri_password
.sip_str_ptr
= scan
;
1078 outurl
->sip_uri_password
.sip_str_len
= uend
- scan
;
1080 while (scan
< uend
&& (SIP_URI_ISUNRESERVED(*scan
) ||
1081 SIP_URI_ISURLESCAPE(scan
, uend
) || SIP_URI_ISOTHER(*scan
) ||
1086 outurl
->sip_uri_errflags
|= SIP_URIERR_PASS
;
1090 * user = 1*( unreserved / escaped / user-unreserved )
1091 * user-unreserved = "&" / "=" / "+" / "$" / "," / ";" / "?" / "/"
1094 sip_uri_parse_user(_sip_uri_t
*outurl
, char *scan
, char *uend
)
1097 outurl
->sip_uri_errflags
|= SIP_URIERR_USER
;
1100 outurl
->sip_uri_user
.sip_str_ptr
= scan
;
1101 outurl
->sip_uri_user
.sip_str_len
= uend
- scan
;
1103 if (sip_uri_parse_tel(scan
, uend
)) {
1104 outurl
->sip_uri_isteluser
= B_TRUE
;
1106 while (scan
< uend
&& (SIP_URI_ISUNRESERVED(*scan
) ||
1107 SIP_URI_ISURLESCAPE(scan
, uend
) || SIP_URI_ISUSER(*scan
))) {
1111 outurl
->sip_uri_errflags
|= SIP_URIERR_USER
;
1116 * the format of port is supposed to be :XXX
1120 sip_uri_parse_port(_sip_uri_t
*outurl
, char *scan
, char *uend
)
1122 if (scan
== uend
|| *scan
!= ':' || scan
+ 1 == uend
) {
1123 outurl
->sip_uri_errflags
|= SIP_URIERR_PORT
;
1128 * parse numeric port number
1130 if (SIP_URI_ISDIGIT(*scan
)) {
1131 outurl
->sip_uri_port
= *scan
- '0';
1132 while (++scan
< uend
&& SIP_URI_ISDIGIT(*scan
)) {
1133 outurl
->sip_uri_port
=
1134 outurl
->sip_uri_port
* 10 + (*scan
- '0');
1135 if (outurl
->sip_uri_port
> 0xffff) {
1136 outurl
->sip_uri_errflags
|= SIP_URIERR_PORT
;
1137 outurl
->sip_uri_port
= 0;
1143 outurl
->sip_uri_errflags
|= SIP_URIERR_PORT
;
1144 outurl
->sip_uri_port
= 0;
1149 * parse an IPv4 address
1150 * 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT
1151 * advances pscan to end of IPv4 address, or after last "." that was
1152 * a valid IPv4 or domain name.
1153 * returns 1 if ipv4 found, 0 otherwise
1156 sip_uri_parse_ipv4(char *scan
, char *uend
)
1161 for (j
= 0; j
< 4; ++j
) {
1162 if (!SIP_URI_ISDIGIT(*scan
))
1165 while (++scan
< uend
&& SIP_URI_ISDIGIT(*scan
)) {
1166 val
= val
* 10 + (*scan
- '0');
1177 if (j
== 4 && scan
== uend
)
1184 * parse an IPv6 address
1185 * IPv6address = hexpart [ ":" IPv4address ]
1186 * IPv4address = 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT
1187 * hexpart = hexseq | hexseq "::" [ hexseq ] | "::" [ hexseq ]
1188 * hexseq = hex4 *( ":" hex4)
1190 * if not found, leaves pscan unchanged, otherwise advances to end
1191 * returns 1 if valid,
1195 sip_uri_parse_ipv6(char *scan
, char *uend
)
1198 unsigned j
= 0; /* index for addr */
1199 unsigned val
= 0; /* hex value */
1200 int zpad
= 0; /* index of :: delimiter */
1208 * check for leading "::", set zpad to the position of the "::"
1210 if (scan
+ 1 < uend
&& scan
[0] == ':' && scan
[1] == ':') {
1218 * loop through up to 16 bytes of IPv6 address
1220 while (scan
< uend
&& j
< 15) {
1221 if (!SIP_URI_ISHEX(*scan
))
1224 val
= SIP_URI_HEXVAL(*scan
);
1225 while (++scan
< uend
&& SIP_URI_ISHEX(*scan
)) {
1226 val
= val
* 16 + SIP_URI_HEXVAL(*scan
);
1232 * always require a delimiter or ]
1237 if (*scan
== '.' && (j
== 12 || (zpad
!= -1 && j
< 12)) &&
1238 mark
< uend
&& sip_uri_parse_ipv4(mark
, uend
- 1) &&
1239 *(uend
- 1) == ']') {
1252 * check for delimiter or ]
1256 * found ":" delimiter, check for "::"
1258 if (++scan
< uend
&& *scan
== ':') {
1262 if (++scan
< uend
&& *scan
== ']') {
1267 } else if (*scan
== ']' && (j
== 16 || zpad
!= -1)) {
1272 * not a valid delimiter
1277 if (zpad
== -1 && j
< 16)
1291 * hostname = *( domainlabel "." ) toplabel [ "." ]
1292 * domainlabel = alphanum / alphanum *( alphanum / "-" ) alphanum
1293 * toplabel = ALPHA / ALPHA *( alphanum / "-" ) alphanum
1296 sip_uri_parse_hostname(char *scan
, char *uend
)
1300 if (scan
< uend
&& SIP_URI_ISALNUM(*scan
)) {
1302 sawalpha
= SIP_URI_ISALPHA(*scan
);
1303 while (SIP_URI_ISHOST(*scan
))
1308 } while (scan
< uend
&& SIP_URI_ISALNUM(*scan
));
1311 if (sawalpha
&& scan
== uend
)
1318 * parse the network path portion of a full URL
1321 sip_uri_parse_netpath(_sip_uri_t
*outurl
, char **pscan
, char *uend
,
1326 char *scan
= *pscan
;
1330 * look for the first high-level delimiter
1333 while (scan
< uend
&& *scan
!= '@')
1336 * handle userinfo section of URL
1338 if (scan
< uend
&& *scan
== '@') {
1343 while (mark
< scan
&& *mark
!= ':')
1345 sip_uri_parse_user(outurl
, mark2
, mark
);
1350 sip_uri_parse_password(outurl
, mark
, scan
);
1355 if (scan
< uend
&& *scan
== '[') { /* look for an IPv6 address */
1356 while (scan
< uend
&& *scan
!= ']')
1360 if (sip_uri_parse_ipv6(mark
, scan
))
1364 while (scan
< uend
&& ((issip
&& !SIP_URI_ISSIPHDELIM(*scan
)) ||
1365 (!issip
&& !SIP_URI_ISABSHDELIM(*scan
)))) {
1370 * look for an IPv4 address
1372 if (mark
< scan
&& SIP_URI_ISDIGIT(*mark
) &&
1373 sip_uri_parse_ipv4(mark
, scan
)) {
1378 * look for a valid host name
1380 if (!gothost
&& mark
< scan
&&
1381 sip_uri_parse_hostname(mark
, scan
)) {
1386 * handle invalid host name
1389 outurl
->sip_uri_errflags
|= SIP_URIERR_HOST
;
1393 outurl
->sip_uri_host
.sip_str_ptr
= mark
;
1394 outurl
->sip_uri_host
.sip_str_len
= scan
- mark
;
1398 * parse the port number
1400 if (scan
< uend
&& *scan
== ':') {
1401 while (scan
< uend
&& ((issip
&& !SIP_URI_ISSIPDELIM(*scan
)) ||
1402 (!issip
&& !SIP_URI_ISABSDELIM(*scan
)))) {
1405 sip_uri_parse_port(outurl
, mark
, scan
);
1409 * set return pointer
1416 * URL = SIP-URI / SIPS-URI / absoluteURI
1419 sip_uri_parse_it(_sip_uri_t
*outurl
, sip_str_t
*uri_str
)
1424 char *str
= uri_str
->sip_str_ptr
;
1425 unsigned urlen
= uri_str
->sip_str_len
;
1428 * reset output parameters
1430 (void) memset(outurl
, 0, sizeof (sip_uri_t
));
1433 * strip enclosing angle brackets
1435 if (urlen
> 1 && str
[0] == '<' && str
[urlen
-1] == '>') {
1442 * strip off space prefix and trailing spaces
1444 while (str
< uend
&& isspace(*str
)) {
1448 while (str
< uend
&& isspace(*(uend
- 1))) {
1454 * strip off "URL:" prefix
1456 if (urlen
> 4 && sip_uri_url_casecmp(str
, "URL:", 4) == 0) {
1462 * parse the scheme name
1465 while (scan
< uend
&& *scan
!= ':')
1467 if (scan
== uend
|| !sip_uri_parse_scheme(outurl
, mark
, scan
)) {
1468 outurl
->sip_uri_errflags
|= SIP_URIERR_SCHEME
;
1472 if ((outurl
->sip_uri_scheme
.sip_str_len
== SIP_SCHEME_LEN
&&
1473 !memcmp(outurl
->sip_uri_scheme
.sip_str_ptr
, SIP_SCHEME
,
1475 (outurl
->sip_uri_scheme
.sip_str_len
== SIPS_SCHEME_LEN
&&
1476 !memcmp(outurl
->sip_uri_scheme
.sip_str_ptr
, SIPS_SCHEME
,
1477 SIPS_SCHEME_LEN
))) {
1478 outurl
->sip_uri_issip
= B_TRUE
;
1480 outurl
->sip_uri_issip
= B_FALSE
;
1482 ++scan
; /* skip ':' */
1484 if (outurl
->sip_uri_issip
) {
1488 sip_uri_parse_netpath(outurl
, &scan
, uend
, B_TRUE
);
1493 if (scan
< uend
&& *scan
== ';') {
1495 while (scan
< uend
&& *scan
!= '?')
1497 sip_uri_parse_params(outurl
, mark
, scan
);
1503 if (scan
< uend
&& *scan
== '?')
1504 sip_uri_parse_headers(outurl
, scan
, uend
);
1505 } else if (scan
< uend
&& scan
[0] == '/') { /* parse absoluteURL */
1509 * authority = srvr / reg-name
1510 * srvr = [ [ userinfo "@" ] hostport ]
1511 * reg-name = 1*(unreserved / escaped / "$" / ","
1512 * / ";" / ":" / "@" / "&" / "=" / "+")
1514 if (scan
< uend
&& *scan
== '/') {
1518 * take authority as srvr
1520 sip_uri_parse_netpath(outurl
, &scan
, uend
, B_FALSE
);
1523 * if srvr failed, take it as reg-name
1526 if (outurl
->sip_uri_errflags
& SIP_URIERR_USER
||
1527 outurl
->sip_uri_errflags
& SIP_URIERR_PASS
||
1528 outurl
->sip_uri_errflags
& SIP_URIERR_HOST
||
1529 outurl
->sip_uri_errflags
& SIP_URIERR_PORT
) {
1531 while (scan
< uend
&& *scan
!= '/' &&
1535 sip_uri_parse_abs_regname(outurl
, mark
, scan
);
1536 if (!(outurl
->sip_uri_errflags
&
1537 SIP_URIERR_REGNAME
)) {
1539 * remove error info of user,
1540 * password, host, port
1542 outurl
->sip_uri_user
.sip_str_ptr
= NULL
;
1543 outurl
->sip_uri_user
.sip_str_len
= 0;
1544 outurl
->sip_uri_errflags
&=
1546 outurl
->sip_uri_password
.sip_str_ptr
=
1548 outurl
->sip_uri_password
.sip_str_len
=
1550 outurl
->sip_uri_errflags
&=
1552 outurl
->sip_uri_host
.sip_str_ptr
= NULL
;
1553 outurl
->sip_uri_host
.sip_str_len
= 0;
1554 outurl
->sip_uri_errflags
&=
1556 outurl
->sip_uri_port
= 0;
1557 outurl
->sip_uri_errflags
&=
1563 * there is no net-path
1570 if (scan
< uend
&& *scan
== '/') {
1572 while (scan
< uend
&& *scan
!= '?')
1574 sip_uri_parse_abs_path(outurl
, mark
, scan
);
1580 if (scan
< uend
&& *scan
== '?')
1581 sip_uri_parse_abs_query(outurl
, scan
, uend
);
1586 sip_uri_parse_abs_opaque(outurl
, scan
, uend
);