/src/kamailio/src/core/parser/parse_uri.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (C) 2001-2003 FhG Fokus |
3 | | * |
4 | | * This file is part of Kamailio, a free SIP server. |
5 | | * |
6 | | * Kamailio is free software; you can redistribute it and/or modify |
7 | | * it under the terms of the GNU General Public License as published by |
8 | | * the Free Software Foundation; either version 2 of the License, or |
9 | | * (at your option) any later version |
10 | | * |
11 | | * Kamailio is distributed in the hope that it will be useful, |
12 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | | * GNU General Public License for more details. |
15 | | * |
16 | | * You should have received a copy of the GNU General Public License |
17 | | * along with this program; if not, write to the Free Software |
18 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
19 | | * |
20 | | */ |
21 | | |
22 | | /** @file |
23 | | * @brief Parser :: Parse URI's |
24 | | * |
25 | | * @ingroup parser |
26 | | */ |
27 | | |
28 | | |
29 | | #include <stdint.h> |
30 | | |
31 | | #include "../globals.h" |
32 | | #include "parse_uri.h" |
33 | | #include <string.h> |
34 | | #include "../dprint.h" |
35 | | #include "../ut.h" /* q_memchr */ |
36 | | #include "../error.h" |
37 | | #include "../core_stats.h" |
38 | | |
39 | | static char _sr_uri_empty_buf[2] = {0}; |
40 | | static str _sr_uri_empty = {_sr_uri_empty_buf, 0}; |
41 | | |
42 | | /* extra chars that should be allowed in URI host */ |
43 | | char *_sr_uri_host_extra_chars = ""; |
44 | | |
45 | | int uri_host_char_allowed(char c) |
46 | 27 | { |
47 | 27 | int i = 0; |
48 | | |
49 | 27 | if(_sr_uri_host_extra_chars == NULL |
50 | 27 | || _sr_uri_host_extra_chars[0] == '\0') { |
51 | 27 | return 0; |
52 | 27 | } |
53 | 0 | while(_sr_uri_host_extra_chars[i] != '\0') { |
54 | 0 | if(_sr_uri_host_extra_chars[i] == c) { |
55 | 0 | return 1; |
56 | 0 | } |
57 | 0 | i++; |
58 | 0 | } |
59 | 0 | return 0; |
60 | 0 | } |
61 | | |
62 | | /* buf= pointer to beginning of uri (sip:x@foo.bar:5060;a=b?h=i) |
63 | | * len= len of uri |
64 | | * returns: fills uri & returns <0 on error or 0 if ok |
65 | | */ |
66 | | int parse_uri(char *buf, int len, struct sip_uri *uri) |
67 | 8.56k | { |
68 | 8.56k | enum states |
69 | 8.56k | { |
70 | 8.56k | URI_INIT, |
71 | 8.56k | URI_USER, |
72 | 8.56k | URI_PASSWORD, |
73 | 8.56k | URI_PASSWORD_ALPHA, |
74 | 8.56k | URI_HOST, |
75 | 8.56k | URI_HOST_P, |
76 | 8.56k | URI_HOST6_P, |
77 | 8.56k | URI_HOST6_END, |
78 | 8.56k | URI_PORT, |
79 | 8.56k | URI_PARAM, |
80 | 8.56k | URI_PARAM_P, |
81 | 8.56k | URI_VAL_P, |
82 | 8.56k | URI_HEADERS, |
83 | | /* param states */ |
84 | | /* transport */ |
85 | 8.56k | PT_T, |
86 | 8.56k | PT_R, |
87 | 8.56k | PT_A, |
88 | 8.56k | PT_N, |
89 | 8.56k | PT_S, |
90 | 8.56k | PT_P, |
91 | 8.56k | PT_O, |
92 | 8.56k | PT_R2, |
93 | 8.56k | PT_T2, |
94 | 8.56k | PT_eq, |
95 | | /* ttl */ |
96 | 8.56k | PTTL_T2, |
97 | 8.56k | PTTL_L, |
98 | 8.56k | PTTL_eq, |
99 | | /* user */ |
100 | 8.56k | PU_U, |
101 | 8.56k | PU_S, |
102 | 8.56k | PU_E, |
103 | 8.56k | PU_R, |
104 | 8.56k | PU_eq, |
105 | | /* method */ |
106 | 8.56k | PM_M, |
107 | 8.56k | PM_E, |
108 | 8.56k | PM_T, |
109 | 8.56k | PM_H, |
110 | 8.56k | PM_O, |
111 | 8.56k | PM_D, |
112 | 8.56k | PM_eq, |
113 | | /* maddr */ |
114 | 8.56k | PMA_A, |
115 | 8.56k | PMA_D, |
116 | 8.56k | PMA_D2, |
117 | 8.56k | PMA_R, |
118 | 8.56k | PMA_eq, |
119 | | /* lr */ |
120 | 8.56k | PLR_L, |
121 | 8.56k | PLR_R_FIN, |
122 | 8.56k | PLR_eq, |
123 | | /* r2 */ |
124 | 8.56k | PR2_R, |
125 | 8.56k | PR2_2_FIN, |
126 | 8.56k | PR2_eq, |
127 | | /* gr */ |
128 | 8.56k | PGR_G, |
129 | 8.56k | PGR_R_FIN, |
130 | 8.56k | PGR_eq, |
131 | | #ifdef USE_COMP |
132 | | /* comp */ |
133 | | PCOMP_C, |
134 | | PCOMP_O, |
135 | | PCOMP_M, |
136 | | PCOMP_P, |
137 | | PCOMP_eq, |
138 | | |
139 | | /* comp values */ |
140 | | /* sigcomp */ |
141 | | VCOMP_S, |
142 | | VCOMP_SIGC_I, |
143 | | VCOMP_SIGC_G, |
144 | | VCOMP_SIGC_C, |
145 | | VCOMP_SIGC_O, |
146 | | VCOMP_SIGC_M, |
147 | | VCOMP_SIGC_P_FIN, |
148 | | /* sergz */ |
149 | | VCOMP_SGZ_E, |
150 | | VCOMP_SGZ_R, |
151 | | VCOMP_SGZ_G, |
152 | | VCOMP_SGZ_Z_FIN, |
153 | | #endif |
154 | | |
155 | | /* transport values */ |
156 | | /* udp */ |
157 | 8.56k | VU_U, |
158 | 8.56k | VU_D, |
159 | 8.56k | VU_P_FIN, |
160 | | /* tcp */ |
161 | 8.56k | VT_T, |
162 | 8.56k | VT_C, |
163 | 8.56k | VT_P_FIN, |
164 | | /* tls */ |
165 | 8.56k | VTLS_L, |
166 | 8.56k | VTLS_S_FIN, |
167 | | /* sctp */ |
168 | 8.56k | VS_S, |
169 | 8.56k | VS_C, |
170 | 8.56k | VS_T, |
171 | 8.56k | VS_P_FIN, |
172 | | /* ws */ |
173 | 8.56k | VW_W, |
174 | 8.56k | VW_S_FIN |
175 | 8.56k | }; |
176 | 8.56k | register enum states state; |
177 | 8.56k | char *s; |
178 | 8.56k | char *b; /* param start */ |
179 | 8.56k | char *v; /* value start */ |
180 | 8.56k | str *param; /* current param */ |
181 | 8.56k | str *param_val; /* current param val */ |
182 | 8.56k | str user; |
183 | 8.56k | str password; |
184 | 8.56k | int port_no; |
185 | 8.56k | register char *p; |
186 | 8.56k | char *end; |
187 | 8.56k | char *pass; |
188 | 8.56k | int found_user; |
189 | 8.56k | int error_headers; |
190 | 8.56k | uint32_t scheme; |
191 | 8.56k | uri_type backup_urit; |
192 | 8.56k | uri_flags backup_urif; |
193 | | |
194 | | #ifdef USE_COMP |
195 | | str comp_str; /* not returned for now */ |
196 | | str comp_val; /* not returned for now */ |
197 | | #endif |
198 | | |
199 | 8.56k | #define SIP_SCH 0x3a706973 |
200 | 8.56k | #define SIPS_SCH 0x73706973 |
201 | 8.56k | #define TEL_SCH 0x3a6c6574 |
202 | 8.56k | #define URN_SCH 0x3a6e7275 |
203 | | |
204 | 8.56k | #define case_port(ch, var) \ |
205 | 70.8k | case ch: \ |
206 | 70.8k | (var) = (var)*10 + ch - '0'; \ |
207 | 70.8k | if((var) > MAX_PORT_VAL) { \ |
208 | 180 | goto error_bad_port; \ |
209 | 180 | } \ |
210 | 70.8k | break |
211 | | |
212 | 8.56k | #define still_at_user \ |
213 | 8.56k | if(found_user == 0) { \ |
214 | 977 | user.s = uri->host.s; \ |
215 | 977 | if(pass) { \ |
216 | 428 | user.len = pass - user.s; \ |
217 | 428 | password.s = pass + 1; \ |
218 | 428 | password.len = p - password.s; \ |
219 | 549 | } else { \ |
220 | 549 | user.len = p - user.s; \ |
221 | 549 | } \ |
222 | | /* save the uri type/scheme */ \ |
223 | 977 | backup_urit = uri->type; \ |
224 | 977 | backup_urif = uri->flags; \ |
225 | | /* everything else is 0 */ \ |
226 | 977 | memset(uri, 0, sizeof(struct sip_uri)); \ |
227 | | /* restore the scheme & flags, copy user & pass */ \ |
228 | 977 | uri->type = backup_urit; \ |
229 | 977 | uri->flags = backup_urif; \ |
230 | 977 | uri->user = user; \ |
231 | 977 | if(pass) \ |
232 | 977 | uri->passwd = password; \ |
233 | 977 | s = p + 1; \ |
234 | 977 | found_user = 1; \ |
235 | 977 | error_headers = 0; \ |
236 | 977 | state = URI_HOST; \ |
237 | 977 | } else \ |
238 | 1.21k | goto error_bad_char |
239 | | |
240 | 8.56k | #define check_host_end \ |
241 | 8.56k | case ':': \ |
242 | | /* found the host */ \ |
243 | 607 | uri->host.s = s; \ |
244 | 607 | uri->host.len = p - s; \ |
245 | 607 | state = URI_PORT; \ |
246 | 607 | s = p + 1; \ |
247 | 607 | break; \ |
248 | 785 | case ';': \ |
249 | 785 | uri->host.s = s; \ |
250 | 785 | uri->host.len = p - s; \ |
251 | 785 | state = URI_PARAM; \ |
252 | 785 | s = p + 1; \ |
253 | 785 | break; \ |
254 | 785 | case '?': \ |
255 | 20 | uri->host.s = s; \ |
256 | 20 | uri->host.len = p - s; \ |
257 | 20 | state = URI_HEADERS; \ |
258 | 20 | s = p + 1; \ |
259 | 20 | break; \ |
260 | 20 | case '&': \ |
261 | 18 | case '@': \ |
262 | 18 | goto error_bad_char |
263 | | |
264 | | |
265 | 8.56k | #define param_set(t_start, v_start) \ |
266 | 40.7k | param->s = (t_start); \ |
267 | 40.7k | param->len = (p - (t_start)); \ |
268 | 40.7k | param_val->s = (v_start); \ |
269 | 40.7k | param_val->len = (p - (v_start)) |
270 | | |
271 | 8.56k | #define semicolon_case \ |
272 | 148k | case ';': \ |
273 | 148k | if(pass) { \ |
274 | 274 | found_user = 1; /* no user, pass cannot contain ';'*/ \ |
275 | 274 | pass = 0; \ |
276 | 274 | } \ |
277 | 148k | state = URI_PARAM /* new param */ |
278 | | |
279 | 8.56k | #define question_case \ |
280 | 8.56k | case '?': \ |
281 | 933 | uri->params.s = s; \ |
282 | 933 | uri->params.len = p - s; \ |
283 | 933 | state = URI_HEADERS; \ |
284 | 933 | s = p + 1; \ |
285 | 933 | if(pass) { \ |
286 | 216 | found_user = 1; /* no user, pass cannot contain '?'*/ \ |
287 | 216 | pass = 0; \ |
288 | 216 | } |
289 | | |
290 | 8.56k | #define colon_case \ |
291 | 37.8k | case ':': \ |
292 | 37.8k | if(found_user == 0) { \ |
293 | | /*might be pass but only if user not found yet*/ \ |
294 | 688 | if(pass) { \ |
295 | 26 | found_user = 1; /* no user */ \ |
296 | 26 | pass = 0; \ |
297 | 662 | } else { \ |
298 | 662 | pass = p; \ |
299 | 662 | } \ |
300 | 688 | } \ |
301 | 37.8k | state = URI_PARAM_P /* generic param */ |
302 | | |
303 | 8.56k | #define param_common_cases \ |
304 | 8.56k | case '@': \ |
305 | | /* ughhh, this is still the user */ \ |
306 | 663 | still_at_user; \ |
307 | 507 | break; \ |
308 | 106k | semicolon_case; \ |
309 | 106k | break; \ |
310 | 106k | question_case; \ |
311 | 636 | break; \ |
312 | 27.1k | colon_case; \ |
313 | 27.1k | break |
314 | | |
315 | 8.56k | #define value_common_cases \ |
316 | 8.56k | case '@': \ |
317 | | /* ughhh, this is still the user */ \ |
318 | 87 | still_at_user; \ |
319 | 47 | break; \ |
320 | 34.2k | semicolon_case; \ |
321 | 34.2k | param_set(b, v); \ |
322 | 34.2k | break; \ |
323 | 34.2k | question_case; \ |
324 | 163 | param_set(b, v); \ |
325 | 163 | break; \ |
326 | 5.15k | colon_case; \ |
327 | 5.15k | state = URI_VAL_P; \ |
328 | 5.15k | break |
329 | | |
330 | 8.56k | #define param_switch(old_state, c1, c2, new_state) \ |
331 | 586k | case old_state: \ |
332 | 586k | switch(*p) { \ |
333 | 322k | case c1: \ |
334 | 530k | case c2: \ |
335 | 530k | state = (new_state); \ |
336 | 530k | break; \ |
337 | 322k | param_common_cases; \ |
338 | 18.4k | default: \ |
339 | 18.4k | state = URI_PARAM_P; \ |
340 | 586k | } \ |
341 | 586k | break |
342 | 8.56k | #define param_switch1(old_state, c1, new_state) \ |
343 | 78.4k | case old_state: \ |
344 | 78.4k | switch(*p) { \ |
345 | 61.0k | case c1: \ |
346 | 61.0k | state = (new_state); \ |
347 | 61.0k | break; \ |
348 | 49 | param_common_cases; \ |
349 | 4.05k | default: \ |
350 | 4.05k | state = URI_PARAM_P; \ |
351 | 78.4k | } \ |
352 | 78.4k | break |
353 | 8.56k | #define param_switch_big(old_state, c1, c2, d1, d2, new_state_c, new_state_d) \ |
354 | 118k | case old_state: \ |
355 | 118k | switch(*p) { \ |
356 | 78.4k | case c1: \ |
357 | 93.5k | case c2: \ |
358 | 93.5k | state = (new_state_c); \ |
359 | 93.5k | break; \ |
360 | 78.4k | case d1: \ |
361 | 19.3k | case d2: \ |
362 | 19.3k | state = (new_state_d); \ |
363 | 19.3k | break; \ |
364 | 9.91k | param_common_cases; \ |
365 | 2.84k | default: \ |
366 | 2.84k | state = URI_PARAM_P; \ |
367 | 118k | } \ |
368 | 118k | break |
369 | 8.56k | #define value_switch(old_state, c1, c2, new_state) \ |
370 | 46.2k | case old_state: \ |
371 | 46.2k | switch(*p) { \ |
372 | 18.4k | case c1: \ |
373 | 28.4k | case c2: \ |
374 | 28.4k | state = (new_state); \ |
375 | 28.4k | break; \ |
376 | 18.4k | value_common_cases; \ |
377 | 4.42k | default: \ |
378 | 4.42k | state = URI_VAL_P; \ |
379 | 46.2k | } \ |
380 | 46.2k | break |
381 | 8.56k | #define value_switch_big(old_state, c1, c2, d1, d2, new_state_c, new_state_d) \ |
382 | 10.4k | case old_state: \ |
383 | 10.4k | switch(*p) { \ |
384 | 1.60k | case c1: \ |
385 | 3.97k | case c2: \ |
386 | 3.97k | state = (new_state_c); \ |
387 | 3.97k | break; \ |
388 | 1.60k | case d1: \ |
389 | 4.74k | case d2: \ |
390 | 4.74k | state = (new_state_d); \ |
391 | 4.74k | break; \ |
392 | 1.33k | value_common_cases; \ |
393 | 438 | default: \ |
394 | 438 | state = URI_VAL_P; \ |
395 | 10.4k | } \ |
396 | 10.4k | break |
397 | | |
398 | 8.56k | #define transport_fin(c_state, proto_no) \ |
399 | 14.8k | case c_state: \ |
400 | 14.8k | switch(*p) { \ |
401 | 40 | case '@': \ |
402 | 40 | still_at_user; \ |
403 | 40 | break; \ |
404 | 5.08k | semicolon_case; \ |
405 | 5.08k | param_set(b, v); \ |
406 | 5.08k | uri->proto = (proto_no); \ |
407 | 5.08k | break; \ |
408 | 83 | question_case; \ |
409 | 83 | param_set(b, v); \ |
410 | 83 | uri->proto = (proto_no); \ |
411 | 83 | break; \ |
412 | 4.26k | colon_case; \ |
413 | 9.66k | default: \ |
414 | 9.66k | state = URI_VAL_P; \ |
415 | 9.66k | break; \ |
416 | 14.8k | } \ |
417 | 14.8k | break |
418 | | |
419 | | |
420 | | #ifdef USE_COMP |
421 | | #define comp_fin(c_state, comp_no) \ |
422 | | case c_state: \ |
423 | | switch(*p) { \ |
424 | | case '@': \ |
425 | | still_at_user; \ |
426 | | break; \ |
427 | | semicolon_case; \ |
428 | | /* param_set(b, v); */ \ |
429 | | uri->comp = (comp_no); \ |
430 | | break; \ |
431 | | question_case; \ |
432 | | /* param_set(b, v) */; \ |
433 | | uri->comp = (comp_no); \ |
434 | | break; \ |
435 | | colon_case; \ |
436 | | default: \ |
437 | | state = URI_VAL_P; \ |
438 | | break; \ |
439 | | } \ |
440 | | break |
441 | | |
442 | | #endif |
443 | | |
444 | | /* init */ |
445 | 8.56k | end = buf + len; |
446 | 8.56k | p = buf + 4; |
447 | 8.56k | found_user = 0; |
448 | 8.56k | error_headers = 0; |
449 | 8.56k | b = v = 0; |
450 | 8.56k | param = param_val = 0; |
451 | 8.56k | pass = 0; |
452 | 8.56k | password.s = 0; /* fixes gcc 4.0 warning */ |
453 | 8.56k | password.len = 0; |
454 | 8.56k | port_no = 0; |
455 | 8.56k | state = URI_INIT; |
456 | 8.56k | memset(uri, 0, sizeof(struct sip_uri)); /* zero it all, just to be sure*/ |
457 | | /*look for sip:, sips:, tel: or urn:*/ |
458 | 8.56k | if(len < 5) |
459 | 847 | goto error_too_short; |
460 | 7.71k | scheme = ((uint32_t)buf[0]) + (((uint32_t)buf[1]) << 8) |
461 | 7.71k | + (((uint32_t)buf[2]) << 16) + (((uint32_t)buf[3]) << 24); |
462 | 7.71k | scheme |= 0x20202020; |
463 | 7.71k | if(scheme == SIP_SCH) { |
464 | 2.48k | uri->type = SIP_URI_T; |
465 | 5.23k | } else if(scheme == SIPS_SCH) { |
466 | 24 | if(buf[4] == ':') { |
467 | 10 | p++; |
468 | 10 | uri->type = SIPS_URI_T; |
469 | 10 | } else |
470 | 14 | goto error_bad_uri; |
471 | 5.21k | } else if(scheme == TEL_SCH) { |
472 | 3.56k | uri->type = TEL_URI_T; |
473 | 3.56k | } else if(scheme == URN_SCH) { |
474 | 1.39k | uri->type = URN_URI_T; |
475 | 1.39k | } else |
476 | 255 | goto error_bad_uri; |
477 | | |
478 | 7.45k | s = p; |
479 | 2.99M | for(; p < end; p++) { |
480 | 2.98M | switch((unsigned char)state) { |
481 | 7.44k | case URI_INIT: |
482 | 7.44k | switch(*p) { |
483 | 660 | case '[': |
484 | | /* uri = [ipv6address]... */ |
485 | 660 | state = URI_HOST6_P; |
486 | 660 | s = p; |
487 | 660 | break; |
488 | 4 | case ']': |
489 | | /* invalid, no uri can start with ']' */ |
490 | 8 | case ':': |
491 | | /* the same as above for ':' */ |
492 | 8 | goto error_bad_char; |
493 | 65 | case '@': /* error no user part, or |
494 | | * be forgiving and accept it ? */ |
495 | 6.77k | default: |
496 | 6.77k | state = URI_USER; |
497 | 7.44k | } |
498 | 7.43k | break; |
499 | 915k | case URI_USER: |
500 | 915k | switch(*p) { |
501 | 217 | case '@': |
502 | | /* found the user*/ |
503 | 217 | uri->user.s = s; |
504 | 217 | uri->user.len = p - s; |
505 | 217 | if(uri->user.len <= 0) { |
506 | | /* at '@' and no user part */ |
507 | 0 | goto error_bad_char; |
508 | 0 | } |
509 | 217 | state = URI_HOST; |
510 | 217 | found_user = 1; |
511 | 217 | s = p + 1; /* skip '@' */ |
512 | 217 | break; |
513 | 1.71k | case ':': |
514 | | /* found the user, or the host? */ |
515 | 1.71k | uri->user.s = s; |
516 | 1.71k | uri->user.len = p - s; |
517 | 1.71k | state = URI_PASSWORD; |
518 | 1.71k | s = p + 1; /* skip ':' */ |
519 | 1.71k | break; |
520 | 4.54k | case ';': |
521 | | /* this could be still the user or |
522 | | * params?*/ |
523 | 4.54k | uri->host.s = s; |
524 | 4.54k | uri->host.len = p - s; |
525 | 4.54k | state = URI_PARAM; |
526 | 4.54k | s = p + 1; |
527 | 4.54k | break; |
528 | 175 | case '?': /* still user or headers? */ |
529 | 175 | uri->host.s = s; |
530 | 175 | uri->host.len = p - s; |
531 | 175 | state = URI_HEADERS; |
532 | 175 | s = p + 1; |
533 | 175 | break; |
534 | | /* almost anything permitted in the user part */ |
535 | 13.2k | case '.': |
536 | 204k | case '-': |
537 | 211k | case '(': |
538 | 214k | case ')': |
539 | | /* tel uri visual separators, set flag meaning, that |
540 | | * user should be normalized before usage |
541 | | */ |
542 | 214k | uri->flags |= URI_USER_NORMALIZE; |
543 | 214k | break; |
544 | 4 | case '[': |
545 | 8 | case ']': /* the user part cannot contain "[]" */ |
546 | 8 | goto error_bad_char; |
547 | 915k | } |
548 | 915k | break; |
549 | 915k | case URI_PASSWORD: /* this can also be the port (missing user)*/ |
550 | 69.2k | switch(*p) { |
551 | 4 | case '@': |
552 | | /* found the password*/ |
553 | 4 | uri->passwd.s = s; |
554 | 4 | uri->passwd.len = p - s; |
555 | 4 | port_no = 0; |
556 | 4 | state = URI_HOST; |
557 | 4 | found_user = 1; |
558 | 4 | s = p + 1; /* skip '@' */ |
559 | 4 | break; |
560 | 1.09k | case ';': |
561 | | /* upps this is the port */ |
562 | 1.09k | uri->port.s = s; |
563 | 1.09k | uri->port.len = p - s; |
564 | 1.09k | uri->port_no = port_no; |
565 | | /* user contains in fact the host */ |
566 | 1.09k | uri->host.s = uri->user.s; |
567 | 1.09k | uri->host.len = uri->user.len; |
568 | 1.09k | uri->user.s = 0; |
569 | 1.09k | uri->user.len = 0; |
570 | 1.09k | state = URI_PARAM; |
571 | 1.09k | found_user = 1; /* there is no user part */ |
572 | 1.09k | s = p + 1; |
573 | 1.09k | break; |
574 | 24 | case '?': |
575 | | /* upps this is the port */ |
576 | 24 | uri->port.s = s; |
577 | 24 | uri->port.len = p - s; |
578 | 24 | uri->port_no = port_no; |
579 | | /* user contains in fact the host */ |
580 | 24 | uri->host.s = uri->user.s; |
581 | 24 | uri->host.len = uri->user.len; |
582 | 24 | uri->user.s = 0; |
583 | 24 | uri->user.len = 0; |
584 | 24 | state = URI_HEADERS; |
585 | 24 | found_user = 1; /* there is no user part */ |
586 | 24 | s = p + 1; |
587 | 24 | break; |
588 | 65.9k | case_port('0', port_no); |
589 | 65.9k | case_port('1', port_no); |
590 | 200 | case_port('2', port_no); |
591 | 195 | case_port('3', port_no); |
592 | 237 | case_port('4', port_no); |
593 | 405 | case_port('5', port_no); |
594 | 396 | case_port('6', port_no); |
595 | 353 | case_port('7', port_no); |
596 | 182 | case_port('8', port_no); |
597 | 172 | case_port('9', port_no); |
598 | 159 | case '[': |
599 | 8 | case ']': |
600 | 12 | case ':': |
601 | 12 | goto error_bad_char; |
602 | 53 | default: |
603 | | /* it can't be the port, non number found */ |
604 | 53 | port_no = 0; |
605 | 53 | state = URI_PASSWORD_ALPHA; |
606 | 69.2k | } |
607 | 69.1k | break; |
608 | 69.1k | case URI_PASSWORD_ALPHA: |
609 | 1.57k | switch(*p) { |
610 | 4 | case '@': |
611 | | /* found the password*/ |
612 | 4 | uri->passwd.s = s; |
613 | 4 | uri->passwd.len = p - s; |
614 | 4 | state = URI_HOST; |
615 | 4 | found_user = 1; |
616 | 4 | s = p + 1; /* skip '@' */ |
617 | 4 | break; |
618 | 4 | case ';': /* contains non-numbers => cannot be port no*/ |
619 | 8 | case '?': |
620 | 8 | goto error_bad_port; |
621 | 4 | case '[': |
622 | 8 | case ']': |
623 | 13 | case ':': |
624 | 13 | goto error_bad_char; |
625 | 1.57k | } |
626 | 1.55k | break; |
627 | 1.55k | case URI_HOST: |
628 | 939 | if(*p == '[') { |
629 | 19 | state = URI_HOST6_P; |
630 | 920 | } else { |
631 | 920 | if(isalnum(*p)) { |
632 | 905 | state = URI_HOST_P; |
633 | 905 | } else { |
634 | 15 | goto error_bad_host; |
635 | 15 | } |
636 | 920 | } |
637 | 924 | break; |
638 | 2.04k | case URI_HOST_P: |
639 | 2.04k | switch(*p) { |
640 | 19 | check_host_end; |
641 | 1.24k | default: |
642 | 1.24k | if(!isalnum(*p) && (*p != '.') && (*p != '-') |
643 | 1.24k | && !uri_host_char_allowed(*p)) { |
644 | 27 | goto error_bad_host; |
645 | 27 | } |
646 | 2.04k | } |
647 | 2.00k | break; |
648 | 2.00k | case URI_HOST6_END: |
649 | 631 | switch(*p) { |
650 | 588 | check_host_end; |
651 | 4 | default: /*no chars allowed after [ipv6] */ |
652 | 4 | goto error_bad_host; |
653 | 631 | } |
654 | 619 | break; |
655 | 1.11k | case URI_HOST6_P: |
656 | 1.11k | switch(*p) { |
657 | 636 | case ']': |
658 | 636 | state = URI_HOST6_END; |
659 | 636 | break; |
660 | 4 | case '[': |
661 | 8 | case '&': |
662 | 12 | case '@': |
663 | 16 | case ';': |
664 | 21 | case '?': |
665 | 21 | goto error_bad_host; |
666 | 1.11k | } |
667 | 1.09k | break; |
668 | 2.79k | case URI_PORT: |
669 | 2.79k | switch(*p) { |
670 | 19 | case ';': |
671 | 19 | uri->port.s = s; |
672 | 19 | uri->port.len = p - s; |
673 | 19 | uri->port_no = port_no; |
674 | 19 | state = URI_PARAM; |
675 | 19 | s = p + 1; |
676 | 19 | break; |
677 | 14 | case '?': |
678 | 14 | uri->port.s = s; |
679 | 14 | uri->port.len = p - s; |
680 | 14 | uri->port_no = port_no; |
681 | 14 | state = URI_HEADERS; |
682 | 14 | s = p + 1; |
683 | 14 | break; |
684 | 546 | case_port('0', port_no); |
685 | 537 | case_port('1', port_no); |
686 | 191 | case_port('2', port_no); |
687 | 193 | case_port('3', port_no); |
688 | 243 | case_port('4', port_no); |
689 | 434 | case_port('5', port_no); |
690 | 425 | case_port('6', port_no); |
691 | 378 | case_port('7', port_no); |
692 | 185 | case_port('8', port_no); |
693 | 186 | case_port('9', port_no); |
694 | 175 | case '&': |
695 | 0 | case '@': |
696 | 0 | case ':': |
697 | 4 | default: |
698 | 4 | goto error_bad_port; |
699 | 2.79k | } |
700 | 2.69k | break; |
701 | 153k | case URI_PARAM: /* beginning of a new param */ |
702 | 153k | switch(*p) { |
703 | 29 | param_common_cases; |
704 | | /* recognized params */ |
705 | 39.9k | case 't': |
706 | 95.2k | case 'T': |
707 | 95.2k | b = p; |
708 | 95.2k | state = PT_T; |
709 | 95.2k | break; |
710 | 6.30k | case 'u': |
711 | 12.5k | case 'U': |
712 | 12.5k | b = p; |
713 | 12.5k | state = PU_U; |
714 | 12.5k | break; |
715 | 14.6k | case 'm': |
716 | 23.7k | case 'M': |
717 | 23.7k | b = p; |
718 | 23.7k | state = PM_M; |
719 | 23.7k | break; |
720 | 3.56k | case 'l': |
721 | 5.74k | case 'L': |
722 | 5.74k | b = p; |
723 | 5.74k | state = PLR_L; |
724 | 5.74k | break; |
725 | 2.69k | case 'r': |
726 | 5.48k | case 'R': |
727 | 5.48k | b = p; |
728 | 5.48k | state = PR2_R; |
729 | 5.48k | break; |
730 | 2.65k | case 'g': |
731 | 5.48k | case 'G': |
732 | 5.48k | b = p; |
733 | 5.48k | state = PGR_G; |
734 | 5.48k | break; |
735 | | #ifdef USE_COMP |
736 | | case 'c': |
737 | | case 'C': |
738 | | b = p; |
739 | | state = PCOMP_C; |
740 | | break; |
741 | | #endif |
742 | 2.90k | default: |
743 | 2.90k | state = URI_PARAM_P; |
744 | 153k | } |
745 | 153k | break; |
746 | 317k | case URI_PARAM_P: /* ignore current param */ |
747 | | /* supported params: |
748 | | * maddr, transport, ttl, lr, user, method, r2 */ |
749 | 317k | switch(*p) { |
750 | 317k | param_common_cases; |
751 | 317k | }; |
752 | 317k | break; |
753 | | /* ugly but fast param names parsing */ |
754 | | /*transport */ |
755 | 95.2k | param_switch_big(PT_T, 'r', 'R', 't', 'T', PT_R, PTTL_T2); |
756 | 95.2k | param_switch(PT_R, 'a', 'A', PT_A); |
757 | 82.8k | param_switch(PT_A, 'n', 'N', PT_N); |
758 | 79.1k | param_switch(PT_N, 's', 'S', PT_S); |
759 | 75.7k | param_switch(PT_S, 'p', 'P', PT_P); |
760 | 64.7k | param_switch(PT_P, 'o', 'O', PT_O); |
761 | 62.1k | param_switch(PT_O, 'r', 'R', PT_R2); |
762 | 59.1k | param_switch(PT_R2, 't', 'T', PT_T2); |
763 | 57.0k | param_switch1(PT_T2, '=', PT_eq); |
764 | | /* value parsing */ |
765 | 53.8k | case PT_eq: |
766 | 48.6k | param = &uri->transport; |
767 | 48.6k | param_val = &uri->transport_val; |
768 | 48.6k | switch(*p) { |
769 | 9 | param_common_cases; |
770 | 1.29k | case 'u': |
771 | 5.60k | case 'U': |
772 | 5.60k | v = p; |
773 | 5.60k | state = VU_U; |
774 | 5.60k | break; |
775 | 5.02k | case 't': |
776 | 10.4k | case 'T': |
777 | 10.4k | v = p; |
778 | 10.4k | state = VT_T; |
779 | 10.4k | break; |
780 | 5.18k | case 's': |
781 | 9.40k | case 'S': |
782 | 9.40k | v = p; |
783 | 9.40k | state = VS_S; |
784 | 9.40k | break; |
785 | 4.40k | case 'w': |
786 | 9.20k | case 'W': |
787 | 9.20k | v = p; |
788 | 9.20k | state = VW_W; |
789 | 9.20k | break; |
790 | 721 | default: |
791 | 721 | v = p; |
792 | 721 | state = URI_VAL_P; |
793 | 48.6k | } |
794 | 48.6k | break; |
795 | | /* generic value */ |
796 | 509k | case URI_VAL_P: |
797 | 509k | switch(*p) { |
798 | 509k | value_common_cases; |
799 | 509k | } |
800 | 509k | break; |
801 | | /* udp */ |
802 | 509k | value_switch(VU_U, 'd', 'D', VU_D); |
803 | 5.57k | value_switch(VU_D, 'p', 'P', VU_P_FIN); |
804 | 3.57k | transport_fin(VU_P_FIN, PROTO_UDP); |
805 | | /* tcp */ |
806 | 10.4k | value_switch_big(VT_T, 'c', 'C', 'l', 'L', VT_C, VTLS_L); |
807 | 10.4k | value_switch(VT_C, 'p', 'P', VT_P_FIN); |
808 | 3.94k | transport_fin(VT_P_FIN, PROTO_TCP); |
809 | | /* tls */ |
810 | 4.72k | value_switch(VTLS_L, 's', 'S', VTLS_S_FIN); |
811 | 4.71k | transport_fin(VTLS_S_FIN, PROTO_TLS); |
812 | | /* sctp */ |
813 | 9.38k | value_switch(VS_S, 'c', 'C', VS_C); |
814 | 9.37k | value_switch(VS_C, 't', 'T', VS_T); |
815 | 6.43k | value_switch(VS_T, 'p', 'P', VS_P_FIN); |
816 | 3.41k | transport_fin(VS_P_FIN, PROTO_SCTP); |
817 | | /* ws */ |
818 | 9.17k | value_switch(VW_W, 's', 'S', VW_S_FIN); |
819 | 9.16k | transport_fin(VW_S_FIN, PROTO_WS); |
820 | | |
821 | | /* ttl */ |
822 | 8.65k | param_switch(PTTL_T2, 'l', 'L', PTTL_L); |
823 | 8.64k | param_switch1(PTTL_L, '=', PTTL_eq); |
824 | 6.15k | case PTTL_eq: |
825 | 3.66k | param = &uri->ttl; |
826 | 3.66k | param_val = &uri->ttl_val; |
827 | 3.66k | switch(*p) { |
828 | 8 | param_common_cases; |
829 | 2.64k | default: |
830 | 2.64k | v = p; |
831 | 2.64k | state = URI_VAL_P; |
832 | 3.66k | } |
833 | 3.66k | break; |
834 | | |
835 | | /* user param */ |
836 | 12.5k | param_switch(PU_U, 's', 'S', PU_S); |
837 | 12.5k | param_switch(PU_S, 'e', 'E', PU_E); |
838 | 9.85k | param_switch(PU_E, 'r', 'R', PU_R); |
839 | 7.28k | param_switch1(PU_R, '=', PU_eq); |
840 | 5.53k | case PU_eq: |
841 | 3.12k | param = &uri->user_param; |
842 | 3.12k | param_val = &uri->user_param_val; |
843 | 3.12k | switch(*p) { |
844 | 8 | param_common_cases; |
845 | 610 | default: |
846 | 610 | v = p; |
847 | 610 | state = URI_VAL_P; |
848 | 3.12k | } |
849 | 3.12k | break; |
850 | | |
851 | | /* method*/ |
852 | 23.7k | param_switch_big(PM_M, 'e', 'E', 'a', 'A', PM_E, PMA_A); |
853 | 23.7k | param_switch(PM_E, 't', 'T', PM_T); |
854 | 10.5k | param_switch(PM_T, 'h', 'H', PM_H); |
855 | 8.69k | param_switch(PM_H, 'o', 'O', PM_O); |
856 | 6.67k | param_switch(PM_O, 'd', 'D', PM_D); |
857 | 4.87k | param_switch1(PM_D, '=', PM_eq); |
858 | 3.22k | case PM_eq: |
859 | 1.44k | param = &uri->method; |
860 | 1.44k | param_val = &uri->method_val; |
861 | 1.44k | switch(*p) { |
862 | 8 | param_common_cases; |
863 | 410 | default: |
864 | 410 | v = p; |
865 | 410 | state = URI_VAL_P; |
866 | 1.44k | } |
867 | 1.44k | break; |
868 | | |
869 | | /*maddr*/ |
870 | 10.6k | param_switch(PMA_A, 'd', 'D', PMA_D); |
871 | 10.6k | param_switch(PMA_D, 'd', 'D', PMA_D2); |
872 | 8.33k | param_switch(PMA_D2, 'r', 'R', PMA_R); |
873 | 6.52k | param_switch1(PMA_R, '=', PMA_eq); |
874 | 4.22k | case PMA_eq: |
875 | 1.37k | param = &uri->maddr; |
876 | 1.37k | param_val = &uri->maddr_val; |
877 | 1.37k | switch(*p) { |
878 | 8 | param_common_cases; |
879 | 391 | default: |
880 | 391 | v = p; |
881 | 391 | state = URI_VAL_P; |
882 | 1.37k | } |
883 | 1.36k | break; |
884 | | |
885 | | /* lr */ |
886 | 5.70k | param_switch(PLR_L, 'r', 'R', PLR_R_FIN); |
887 | 5.70k | case PLR_R_FIN: |
888 | 3.45k | switch(*p) { |
889 | 8 | case '@': |
890 | 8 | still_at_user; |
891 | 4 | break; |
892 | 1.67k | case '=': |
893 | 1.67k | state = PLR_eq; |
894 | 1.67k | break; |
895 | 969 | semicolon_case; |
896 | 969 | uri->lr.s = b; |
897 | 969 | uri->lr.len = (p - b); |
898 | 969 | break; |
899 | 17 | question_case; |
900 | 17 | uri->lr.s = b; |
901 | 17 | uri->lr.len = (p - b); |
902 | 17 | break; |
903 | 392 | colon_case; |
904 | 392 | break; |
905 | 401 | default: |
906 | 401 | state = URI_PARAM_P; |
907 | 3.45k | } |
908 | 3.45k | break; |
909 | | /* handle lr=something case */ |
910 | 3.45k | case PLR_eq: |
911 | 1.65k | param = &uri->lr; |
912 | 1.65k | param_val = &uri->lr_val; |
913 | 1.65k | switch(*p) { |
914 | 8 | param_common_cases; |
915 | 452 | default: |
916 | 452 | v = p; |
917 | 452 | state = URI_VAL_P; |
918 | 1.65k | } |
919 | 1.65k | break; |
920 | | /* r2 */ |
921 | 5.45k | param_switch1(PR2_R, '2', PR2_2_FIN); |
922 | 5.44k | case PR2_2_FIN: |
923 | 2.71k | switch(*p) { |
924 | 8 | case '@': |
925 | 8 | still_at_user; |
926 | 4 | break; |
927 | 1.37k | case '=': |
928 | 1.37k | state = PR2_eq; |
929 | 1.37k | break; |
930 | 531 | semicolon_case; |
931 | 531 | uri->r2.s = b; |
932 | 531 | uri->r2.len = (p - b); |
933 | 531 | break; |
934 | 17 | question_case; |
935 | 17 | uri->r2.s = b; |
936 | 17 | uri->r2.len = (p - b); |
937 | 17 | break; |
938 | 392 | colon_case; |
939 | 392 | break; |
940 | 400 | default: |
941 | 400 | state = URI_PARAM_P; |
942 | 2.71k | } |
943 | 2.71k | break; |
944 | | /* handle lr=something case */ |
945 | 2.71k | case PR2_eq: |
946 | 1.35k | param = &uri->r2; |
947 | 1.35k | param_val = &uri->r2_val; |
948 | 1.35k | switch(*p) { |
949 | 8 | param_common_cases; |
950 | 481 | default: |
951 | 481 | v = p; |
952 | 481 | state = URI_VAL_P; |
953 | 1.35k | } |
954 | 1.35k | break; |
955 | | /* gr */ |
956 | 5.45k | param_switch(PGR_G, 'r', 'R', PGR_R_FIN); |
957 | 5.45k | case PGR_R_FIN: |
958 | 3.46k | switch(*p) { |
959 | 8 | case '@': |
960 | 8 | still_at_user; |
961 | 4 | break; |
962 | 1.45k | case '=': |
963 | 1.45k | state = PGR_eq; |
964 | 1.45k | break; |
965 | 1.14k | semicolon_case; |
966 | 1.14k | uri->gr.s = b; |
967 | 1.14k | uri->gr.len = (p - b); |
968 | 1.14k | break; |
969 | 17 | question_case; |
970 | 17 | uri->gr.s = b; |
971 | 17 | uri->gr.len = (p - b); |
972 | 17 | break; |
973 | 392 | colon_case; |
974 | 392 | break; |
975 | 442 | default: |
976 | 442 | state = URI_PARAM_P; |
977 | 3.46k | } |
978 | 3.45k | break; |
979 | | /* handle gr=something case */ |
980 | 3.45k | case PGR_eq: |
981 | 1.44k | param = &uri->gr; |
982 | 1.44k | param_val = &uri->gr_val; |
983 | 1.44k | switch(*p) { |
984 | 8 | param_common_cases; |
985 | 559 | default: |
986 | 559 | v = p; |
987 | 559 | state = URI_VAL_P; |
988 | 1.44k | } |
989 | 1.44k | break; |
990 | | |
991 | | #ifdef USE_COMP |
992 | | param_switch(PCOMP_C, 'o', 'O', PCOMP_O); |
993 | | param_switch(PCOMP_O, 'm', 'M', PCOMP_M); |
994 | | param_switch(PCOMP_M, 'p', 'P', PCOMP_P); |
995 | | param_switch1(PCOMP_P, '=', PCOMP_eq); |
996 | | /* value */ |
997 | | case PCOMP_eq: |
998 | | param = &comp_str; |
999 | | param_val = &comp_val; |
1000 | | switch(*p) { |
1001 | | param_common_cases; |
1002 | | case 's': |
1003 | | case 'S': |
1004 | | v = p; |
1005 | | state = VCOMP_S; |
1006 | | break; |
1007 | | default: |
1008 | | v = p; |
1009 | | state = URI_VAL_P; |
1010 | | } |
1011 | | break; |
1012 | | /* sigcomp*/ |
1013 | | value_switch_big( |
1014 | | VCOMP_S, 'i', 'I', 'e', 'E', VCOMP_SIGC_I, VCOMP_SGZ_E); |
1015 | | value_switch(VCOMP_SIGC_I, 'g', 'G', VCOMP_SIGC_G); |
1016 | | value_switch(VCOMP_SIGC_G, 'c', 'C', VCOMP_SIGC_C); |
1017 | | value_switch(VCOMP_SIGC_C, 'o', 'O', VCOMP_SIGC_O); |
1018 | | value_switch(VCOMP_SIGC_O, 'm', 'M', VCOMP_SIGC_M); |
1019 | | value_switch(VCOMP_SIGC_M, 'p', 'P', VCOMP_SIGC_P_FIN); |
1020 | | comp_fin(VCOMP_SIGC_P_FIN, COMP_SIGCOMP); |
1021 | | |
1022 | | /* sergz*/ |
1023 | | value_switch(VCOMP_SGZ_E, 'r', 'R', VCOMP_SGZ_R); |
1024 | | value_switch(VCOMP_SGZ_R, 'g', 'G', VCOMP_SGZ_G); |
1025 | | value_switch(VCOMP_SGZ_G, 'z', 'Z', VCOMP_SGZ_Z_FIN); |
1026 | | comp_fin(VCOMP_SGZ_Z_FIN, COMP_SERGZ); |
1027 | | #endif |
1028 | | |
1029 | | |
1030 | 74.7k | case URI_HEADERS: |
1031 | | /* for now nobody needs them so we completely ignore the |
1032 | | * headers (they are not allowed in request uri) --andrei */ |
1033 | 74.7k | switch(*p) { |
1034 | 396 | case '@': |
1035 | | /* yak, we are still at user */ |
1036 | 396 | still_at_user; |
1037 | 391 | break; |
1038 | 2.75k | case ';': |
1039 | | /* we might be still parsing user, try it */ |
1040 | 2.75k | if(found_user) |
1041 | 10 | goto error_bad_char; |
1042 | 2.74k | error_headers = 1; /* if this is not the user |
1043 | | we have an error */ |
1044 | | /* if pass is set => it cannot be user:pass |
1045 | | * => error (';') is illegal in a header */ |
1046 | 2.74k | if(pass) |
1047 | 4 | goto error_headers; |
1048 | 2.73k | break; |
1049 | 2.73k | case ':': |
1050 | 516 | if(found_user == 0) { |
1051 | | /*might be pass but only if user not found yet*/ |
1052 | 126 | if(pass) { |
1053 | 5 | found_user = 1; /* no user */ |
1054 | 5 | pass = 0; |
1055 | 121 | } else { |
1056 | 121 | pass = p; |
1057 | 121 | } |
1058 | 126 | } |
1059 | 516 | break; |
1060 | 434 | case '?': |
1061 | 434 | if(pass) { |
1062 | 5 | found_user = |
1063 | 5 | 1; /* no user, pass cannot contain '?'*/ |
1064 | 5 | pass = 0; |
1065 | 5 | } |
1066 | 434 | break; |
1067 | 74.7k | } |
1068 | 74.7k | break; |
1069 | 74.7k | default: |
1070 | 0 | goto error_bug; |
1071 | 2.98M | } |
1072 | 2.98M | } |
1073 | | /*end of uri */ |
1074 | 6.88k | switch(state) { |
1075 | 4 | case URI_INIT: /* error empty uri */ |
1076 | 4 | goto error_too_short; |
1077 | 121 | case URI_USER: |
1078 | | /* this is the host, it can't be the user */ |
1079 | 121 | if(found_user) |
1080 | 0 | goto error_bad_uri; |
1081 | 121 | uri->host.s = s; |
1082 | 121 | uri->host.len = p - s; |
1083 | 121 | state = URI_HOST; |
1084 | 121 | break; |
1085 | 438 | case URI_PASSWORD: |
1086 | | /* this is the port, it can't be the passwd */ |
1087 | 438 | if(found_user) |
1088 | 0 | goto error_bad_port; |
1089 | 438 | uri->port.s = s; |
1090 | 438 | uri->port.len = p - s; |
1091 | 438 | uri->port_no = port_no; |
1092 | 438 | uri->host = uri->user; |
1093 | 438 | uri->user.s = 0; |
1094 | 438 | uri->user.len = 0; |
1095 | 438 | break; |
1096 | 28 | case URI_PASSWORD_ALPHA: |
1097 | | /* it might be an urn, check scheme and set host */ |
1098 | 28 | if(scheme == URN_SCH) { |
1099 | 7 | uri->host.s = s; |
1100 | 7 | uri->host.len = p - s; |
1101 | 7 | LM_DBG("parsed urn scheme with host: %.*s\n", uri->host.len, |
1102 | 7 | uri->host.s); |
1103 | | /* this is the port, it can't be the passwd */ |
1104 | 7 | } else |
1105 | 21 | goto error_bad_port; |
1106 | 7 | break; |
1107 | 75 | case URI_HOST_P: |
1108 | 80 | case URI_HOST6_END: |
1109 | 80 | uri->host.s = s; |
1110 | 80 | uri->host.len = p - s; |
1111 | 80 | break; |
1112 | 263 | case URI_HOST: /* error: null host */ |
1113 | 285 | case URI_HOST6_P: /* error: unterminated ipv6 reference*/ |
1114 | 285 | goto error_bad_host; |
1115 | 476 | case URI_PORT: |
1116 | 476 | uri->port.s = s; |
1117 | 476 | uri->port.len = p - s; |
1118 | 476 | uri->port_no = port_no; |
1119 | 476 | break; |
1120 | 1.10k | case URI_PARAM: |
1121 | 2.51k | case URI_PARAM_P: |
1122 | | /* intermediate param states */ |
1123 | 2.55k | case PT_T: /* transport */ |
1124 | 2.58k | case PT_R: |
1125 | 2.61k | case PT_A: |
1126 | 2.64k | case PT_N: |
1127 | 2.67k | case PT_S: |
1128 | 2.70k | case PT_P: |
1129 | 2.73k | case PT_O: |
1130 | 2.76k | case PT_R2: |
1131 | 2.78k | case PT_T2: |
1132 | 2.79k | case PT_eq: /* ignore empty transport params */ |
1133 | 2.82k | case PTTL_T2: /* ttl */ |
1134 | 2.85k | case PTTL_L: |
1135 | 2.87k | case PTTL_eq: |
1136 | 2.90k | case PU_U: /* user */ |
1137 | 2.93k | case PU_S: |
1138 | 2.96k | case PU_E: |
1139 | 2.99k | case PU_R: |
1140 | 3.00k | case PU_eq: |
1141 | 3.03k | case PM_M: /* method */ |
1142 | 3.06k | case PM_E: |
1143 | 3.09k | case PM_T: |
1144 | 3.12k | case PM_H: |
1145 | 3.14k | case PM_O: |
1146 | 3.17k | case PM_D: |
1147 | 3.18k | case PM_eq: |
1148 | 3.21k | case PLR_L: /* lr */ |
1149 | 3.25k | case PR2_R: /* r2 */ |
1150 | 3.28k | case PGR_G: /* gr */ |
1151 | | #ifdef USE_COMP |
1152 | | case PCOMP_C: |
1153 | | case PCOMP_O: |
1154 | | case PCOMP_M: |
1155 | | case PCOMP_P: |
1156 | | case PCOMP_eq: |
1157 | | #endif |
1158 | 3.28k | uri->params.s = s; |
1159 | 3.28k | uri->params.len = p - s; |
1160 | 3.28k | break; |
1161 | | /* fin param states */ |
1162 | 28 | case PLR_R_FIN: |
1163 | 42 | case PLR_eq: |
1164 | 42 | uri->params.s = s; |
1165 | 42 | uri->params.len = p - s; |
1166 | 42 | uri->lr.s = b; |
1167 | 42 | uri->lr.len = p - b; |
1168 | 42 | break; |
1169 | 11 | case PR2_2_FIN: |
1170 | 23 | case PR2_eq: |
1171 | 23 | uri->params.s = s; |
1172 | 23 | uri->params.len = p - s; |
1173 | 23 | uri->r2.s = b; |
1174 | 23 | uri->r2.len = p - b; |
1175 | 23 | break; |
1176 | 32 | case PGR_R_FIN: |
1177 | 44 | case PGR_eq: |
1178 | 44 | uri->params.s = s; |
1179 | 44 | uri->params.len = p - s; |
1180 | 44 | uri->gr.s = b; |
1181 | 44 | uri->gr.len = p - b; |
1182 | 44 | break; |
1183 | 837 | case URI_VAL_P: |
1184 | | /* intermediate value states */ |
1185 | 862 | case VU_U: |
1186 | 889 | case VU_D: |
1187 | 915 | case VT_T: |
1188 | 944 | case VT_C: |
1189 | 972 | case VTLS_L: |
1190 | 996 | case VS_S: |
1191 | 1.02k | case VS_C: |
1192 | 1.05k | case VS_T: |
1193 | 1.08k | case VW_W: |
1194 | 1.08k | uri->params.s = s; |
1195 | 1.08k | uri->params.len = p - s; |
1196 | 1.08k | param_set(b, v); |
1197 | 1.08k | break; |
1198 | | #ifdef USE_COMP |
1199 | | case VCOMP_S: |
1200 | | case VCOMP_SIGC_I: |
1201 | | case VCOMP_SIGC_G: |
1202 | | case VCOMP_SIGC_C: |
1203 | | case VCOMP_SIGC_O: |
1204 | | case VCOMP_SIGC_M: |
1205 | | case VCOMP_SGZ_E: |
1206 | | case VCOMP_SGZ_R: |
1207 | | case VCOMP_SGZ_G: |
1208 | | /* unrecognized comp method, assume none */ |
1209 | | uri->params.s = s; |
1210 | | uri->params.len = p - s; |
1211 | | /* uri->comp=COMP_NONE ; */ |
1212 | | break; |
1213 | | #endif |
1214 | | /* fin value states */ |
1215 | 19 | case VU_P_FIN: |
1216 | 19 | uri->params.s = s; |
1217 | 19 | uri->params.len = p - s; |
1218 | 19 | param_set(b, v); |
1219 | 19 | uri->proto = PROTO_UDP; |
1220 | 19 | break; |
1221 | 22 | case VT_P_FIN: |
1222 | 22 | uri->params.s = s; |
1223 | 22 | uri->params.len = p - s; |
1224 | 22 | param_set(b, v); |
1225 | 22 | uri->proto = PROTO_TCP; |
1226 | 22 | break; |
1227 | 22 | case VTLS_S_FIN: |
1228 | 22 | uri->params.s = s; |
1229 | 22 | uri->params.len = p - s; |
1230 | 22 | param_set(b, v); |
1231 | 22 | uri->proto = PROTO_TLS; |
1232 | 22 | break; |
1233 | 23 | case VS_P_FIN: |
1234 | 23 | uri->params.s = s; |
1235 | 23 | uri->params.len = p - s; |
1236 | 23 | param_set(b, v); |
1237 | 23 | uri->proto = PROTO_SCTP; |
1238 | 23 | break; |
1239 | 28 | case VW_S_FIN: |
1240 | 28 | uri->params.s = s; |
1241 | 28 | uri->params.len = p - s; |
1242 | 28 | param_set(b, v); |
1243 | 28 | uri->proto = PROTO_WS; |
1244 | 28 | break; |
1245 | | #ifdef USE_COMP |
1246 | | case VCOMP_SIGC_P_FIN: |
1247 | | uri->params.s = s; |
1248 | | uri->params.len = p - s; |
1249 | | /* param_set(b, v); */ |
1250 | | uri->comp = COMP_SIGCOMP; |
1251 | | break; |
1252 | | case VCOMP_SGZ_Z_FIN: |
1253 | | uri->params.s = s; |
1254 | | uri->params.len = p - s; |
1255 | | /* param_set(b, v); */ |
1256 | | uri->comp = COMP_SERGZ; |
1257 | | break; |
1258 | | #endif |
1259 | | /* headers */ |
1260 | 756 | case URI_HEADERS: |
1261 | 756 | uri->headers.s = s; |
1262 | 756 | uri->headers.len = p - s; |
1263 | 756 | if(error_headers) |
1264 | 18 | goto error_headers; |
1265 | 738 | break; |
1266 | 738 | default: |
1267 | 108 | goto error_bug; |
1268 | 6.88k | } |
1269 | 6.44k | switch(uri->type) { |
1270 | 4 | case SIPS_URI_T: |
1271 | 2.12k | case SIP_URI_T: |
1272 | | /* save the original sip: URI parameters in sip_params */ |
1273 | 2.12k | uri->sip_params = uri->params; |
1274 | 2.12k | if((phone2tel) && (uri->user_param_val.len == 5) |
1275 | 2.12k | && (strncmp(uri->user_param_val.s, "phone", 5) == 0)) { |
1276 | 60 | uri->type = TEL_URI_T; |
1277 | 60 | uri->flags |= URI_SIP_USER_PHONE; |
1278 | | /* move params from user into uri->params */ |
1279 | 60 | p = q_memchr(uri->user.s, ';', uri->user.len); |
1280 | 60 | if(p) { |
1281 | | /* NOTE: |
1282 | | * specialized uri params (user, maddr, etc.) still hold |
1283 | | * the values from the sip-uri envelope |
1284 | | * while uri->params point to the params in the embedded tel uri |
1285 | | */ |
1286 | 14 | uri->params.s = p + 1; |
1287 | 14 | uri->params.len = |
1288 | 14 | uri->user.s + uri->user.len - uri->params.s; |
1289 | 14 | uri->user.len = p - uri->user.s; |
1290 | 46 | } else { |
1291 | 46 | uri->params.s = 0; |
1292 | 46 | uri->params.len = 0; |
1293 | 46 | } |
1294 | 2.06k | } else { |
1295 | 2.06k | uri->flags &= ~URI_USER_NORMALIZE; |
1296 | 2.06k | } |
1297 | 2.12k | break; |
1298 | 3.07k | case TEL_URI_T: |
1299 | 3.07k | case TELS_URI_T: |
1300 | | /* fix tel uris, move the number in uri and empty the host */ |
1301 | 3.07k | uri->user = uri->host; |
1302 | 3.07k | uri->host = _sr_uri_empty; |
1303 | 3.07k | break; |
1304 | | /* urn: do nothing */ |
1305 | 1.24k | case URN_URI_T: |
1306 | 1.24k | break; |
1307 | 0 | case ERROR_URI_T: |
1308 | 0 | LM_ERR("parse uri unexpected error (BUG?)\n"); |
1309 | 0 | goto error_bad_uri; |
1310 | 0 | break; /* do nothing, avoids a compilation warning */ |
1311 | 6.44k | } |
1312 | | |
1313 | | /* common sanity checks */ |
1314 | 6.44k | if(uri->port.len > 5) { |
1315 | | /* port value too large */ |
1316 | 32 | goto error_invalid_port; |
1317 | 32 | } |
1318 | 6.41k | if(uri->host.len > 0 && uri->user.len <= 0 && uri->host.s > buf |
1319 | 6.41k | && (*(uri->host.s - 1) == '@' || *uri->host.s == '@')) { |
1320 | | /* '@' before host, but no user part */ |
1321 | 36 | goto error_bad_uri; |
1322 | 36 | } |
1323 | | |
1324 | | #ifdef EXTRA_DEBUG |
1325 | | /* do stuff */ |
1326 | | LM_DBG("state=%d\n", state); |
1327 | | LM_DBG("parsed uri:\n type=%d user=<%.*s>(%d)\n passwd=<%.*s>(%d)\n" |
1328 | | " host=<%.*s>(%d)\n port=<%.*s>(%d): %d\n params=<%.*s>(%d)\n" |
1329 | | " headers=<%.*s>(%d)\n", |
1330 | | uri->type, uri->user.len, ZSW(uri->user.s), uri->user.len, |
1331 | | uri->passwd.len, ZSW(uri->passwd.s), uri->passwd.len, uri->host.len, |
1332 | | ZSW(uri->host.s), uri->host.len, uri->port.len, ZSW(uri->port.s), |
1333 | | uri->port.len, uri->port_no, uri->params.len, ZSW(uri->params.s), |
1334 | | uri->params.len, uri->headers.len, ZSW(uri->headers.s), |
1335 | | uri->headers.len); |
1336 | | LM_DBG(" uri flags : "); |
1337 | | if(uri->flags & URI_USER_NORMALIZE) |
1338 | | LM_DBG("user_need_norm "); |
1339 | | if(uri->flags & URI_SIP_USER_PHONE) |
1340 | | LM_DBG("sip_user_phone "); |
1341 | | LM_DBG(" value=%d\n", uri->flags); |
1342 | | LM_DBG(" uri params:\n transport=<%.*s>, val=<%.*s>, proto=%d\n", |
1343 | | uri->transport.len, ZSW(uri->transport.s), uri->transport_val.len, |
1344 | | ZSW(uri->transport_val.s), uri->proto); |
1345 | | LM_DBG(" user-param=<%.*s>, val=<%.*s>\n", uri->user_param.len, |
1346 | | ZSW(uri->user_param.s), uri->user_param_val.len, |
1347 | | ZSW(uri->user_param_val.s)); |
1348 | | LM_DBG(" method=<%.*s>, val=<%.*s>\n", uri->method.len, |
1349 | | ZSW(uri->method.s), uri->method_val.len, ZSW(uri->method_val.s)); |
1350 | | LM_DBG(" ttl=<%.*s>, val=<%.*s>\n", uri->ttl.len, ZSW(uri->ttl.s), |
1351 | | uri->ttl_val.len, ZSW(uri->ttl_val.s)); |
1352 | | LM_DBG(" maddr=<%.*s>, val=<%.*s>\n", uri->maddr.len, ZSW(uri->maddr.s), |
1353 | | uri->maddr_val.len, ZSW(uri->maddr_val.s)); |
1354 | | LM_DBG(" lr=<%.*s>\n", uri->lr.len, ZSW(uri->lr.s)); |
1355 | | LM_DBG(" r2=<%.*s>\n", uri->r2.len, ZSW(uri->r2.s)); |
1356 | | #ifdef USE_COMP |
1357 | | LM_DBG(" comp=%d\n", uri->comp); |
1358 | | #endif |
1359 | | |
1360 | | #endif |
1361 | 6.38k | return 0; |
1362 | | |
1363 | 851 | error_too_short: |
1364 | 851 | LM_DBG("uri too short: <%.*s> (%d)\n", len, ZSW(buf), len); |
1365 | 851 | goto error_exit; |
1366 | 302 | error_bad_char: |
1367 | 302 | LM_DBG("bad char '%c' in state %d" |
1368 | 302 | " parsed: <%.*s> (%d) / <%.*s> (%d)\n", |
1369 | 302 | *p, state, (int)(p - buf), ZSW(buf), (int)(p - buf), len, ZSW(buf), |
1370 | 0 | len); |
1371 | 302 | goto error_exit; |
1372 | 352 | error_bad_host: |
1373 | 352 | LM_DBG("bad host in uri (error at char %c in" |
1374 | 352 | " state %d) parsed: <%.*s>(%d) /<%.*s> (%d)\n", |
1375 | 352 | *p, state, (int)(p - buf), ZSW(buf), (int)(p - buf), len, ZSW(buf), |
1376 | 0 | len); |
1377 | 352 | goto error_exit; |
1378 | 213 | error_bad_port: |
1379 | 213 | LM_DBG("bad port in uri (error at char %c in" |
1380 | 213 | " state %d) parsed: <%.*s>(%d) /<%.*s> (%d)\n", |
1381 | 213 | *p, state, (int)(p - buf), ZSW(buf), (int)(p - buf), len, ZSW(buf), |
1382 | 0 | len); |
1383 | 213 | goto error_exit; |
1384 | 32 | error_invalid_port: |
1385 | 32 | LM_DBG("bad port in uri: [%.*s] in <%.*s>\n", uri->port.len, uri->port.s, |
1386 | 0 | len, ZSW(buf)); |
1387 | 32 | goto error_exit; |
1388 | 305 | error_bad_uri: |
1389 | 305 | LM_DBG("bad uri, state %d parsed: <%.*s> (%d) / <%.*s> (%d)\n", state, |
1390 | 0 | (int)(p - buf), ZSW(buf), (int)(p - buf), len, ZSW(buf), len); |
1391 | 305 | goto error_exit; |
1392 | 22 | error_headers: |
1393 | 22 | LM_DBG("bad uri headers: <%.*s>(%d) / <%.*s>(%d)\n", uri->headers.len, |
1394 | 0 | ZSW(uri->headers.s), uri->headers.len, len, ZSW(buf), len); |
1395 | 22 | goto error_exit; |
1396 | 108 | error_bug: |
1397 | 216 | LM_CRIT("BUG: bad state %d parsed: <%.*s> (%d) / <%.*s> (%d)\n", state, |
1398 | 216 | (int)(p - buf), ZSW(buf), (int)(p - buf), len, ZSW(buf), len); |
1399 | 2.18k | error_exit: |
1400 | 2.18k | ser_error = E_BAD_URI; |
1401 | 2.18k | uri->type = ERROR_URI_T; |
1402 | 2.18k | STATS_BAD_URI(); |
1403 | 2.18k | return E_BAD_URI; |
1404 | 108 | } |
1405 | | |
1406 | | |
1407 | | static inline int _parse_ruri(str *uri, int *status, struct sip_uri *parsed_uri) |
1408 | 0 | { |
1409 | 0 | if(*status) |
1410 | 0 | return 1; |
1411 | | |
1412 | 0 | if(parse_uri(uri->s, uri->len, parsed_uri) < 0) { |
1413 | 0 | LM_ERR("bad uri <%.*s>\n", uri->len, ZSW(uri->s)); |
1414 | 0 | *status = 0; |
1415 | 0 | return -1; |
1416 | 0 | } |
1417 | 0 | *status = 1; |
1418 | 0 | return 1; |
1419 | 0 | } Unexecuted instantiation: fuzz_uri.c:_parse_ruri Unexecuted instantiation: fuzz_parse_msg.c:_parse_ruri |
1420 | | |
1421 | | int parse_sip_msg_uri(struct sip_msg *msg) |
1422 | 0 | { |
1423 | 0 | char *tmp; |
1424 | 0 | int tmp_len; |
1425 | 0 | if(msg->parsed_uri_ok) |
1426 | 0 | return 1; |
1427 | | |
1428 | 0 | if(msg->new_uri.s) { |
1429 | 0 | tmp = msg->new_uri.s; |
1430 | 0 | tmp_len = msg->new_uri.len; |
1431 | 0 | } else { |
1432 | 0 | tmp = msg->first_line.u.request.uri.s; |
1433 | 0 | tmp_len = msg->first_line.u.request.uri.len; |
1434 | 0 | } |
1435 | 0 | if(parse_uri(tmp, tmp_len, &msg->parsed_uri) < 0) { |
1436 | 0 | LM_DBG("bad uri <%.*s>\n", tmp_len, tmp); |
1437 | 0 | msg->parsed_uri_ok = 0; |
1438 | 0 | return -1; |
1439 | 0 | } |
1440 | 0 | msg->parsed_uri_ok = 1; |
1441 | 0 | return 1; |
1442 | 0 | } |
1443 | | |
1444 | | int parse_orig_ruri(struct sip_msg *msg) |
1445 | 0 | { |
1446 | 0 | int ret; |
1447 | |
|
1448 | 0 | ret = _parse_ruri(&REQ_LINE(msg).uri, &msg->parsed_orig_ruri_ok, |
1449 | 0 | &msg->parsed_orig_ruri); |
1450 | 0 | if(ret < 0) |
1451 | 0 | LM_ERR("parse orig ruri failed\n"); |
1452 | 0 | return ret; |
1453 | 0 | } |
1454 | | |
1455 | | int normalize_tel_user(char *res, str *src) |
1456 | 0 | { |
1457 | 0 | int i, l; |
1458 | 0 | l = 0; |
1459 | 0 | for(i = 0; i < src->len; i++) { |
1460 | 0 | switch(src->s[i]) { |
1461 | 0 | case '-': |
1462 | 0 | case '.': |
1463 | 0 | case '(': |
1464 | 0 | case ')': |
1465 | 0 | break; |
1466 | 0 | default: |
1467 | 0 | res[l++] = src->s[i]; |
1468 | 0 | } |
1469 | 0 | } |
1470 | 0 | return l; |
1471 | 0 | } |
1472 | | |
1473 | | |
1474 | | str s_sip = STR_STATIC_INIT("sip"); |
1475 | | str s_sips = STR_STATIC_INIT("sips"); |
1476 | | str s_tel = STR_STATIC_INIT("tel"); |
1477 | | str s_tels = STR_STATIC_INIT("tels"); |
1478 | | str s_urn = STR_STATIC_INIT("urn"); |
1479 | | static str s_null = STR_STATIC_INIT(""); |
1480 | | |
1481 | | void uri_type_to_str(uri_type type, str *s) |
1482 | 0 | { |
1483 | 0 | switch(type) { |
1484 | 0 | case SIP_URI_T: |
1485 | 0 | *s = s_sip; |
1486 | 0 | break; |
1487 | 0 | case SIPS_URI_T: |
1488 | 0 | *s = s_sips; |
1489 | 0 | break; |
1490 | 0 | case TEL_URI_T: |
1491 | 0 | *s = s_tel; |
1492 | 0 | break; |
1493 | 0 | case TELS_URI_T: |
1494 | 0 | *s = s_tels; |
1495 | 0 | break; |
1496 | 0 | case URN_URI_T: |
1497 | 0 | *s = s_urn; |
1498 | 0 | break; |
1499 | 0 | default: |
1500 | 0 | *s = s_null; |
1501 | 0 | } |
1502 | 0 | } |
1503 | | |
1504 | | static str s_udp = STR_STATIC_INIT("udp"); |
1505 | | static str s_tcp = STR_STATIC_INIT("tcp"); |
1506 | | static str s_tls = STR_STATIC_INIT("tls"); |
1507 | | static str s_sctp = STR_STATIC_INIT("sctp"); |
1508 | | static str s_ws = STR_STATIC_INIT("ws"); |
1509 | | |
1510 | | void proto_type_to_str(unsigned short type, str *s) |
1511 | 0 | { |
1512 | 0 | switch(type) { |
1513 | 0 | case PROTO_UDP: |
1514 | 0 | *s = s_udp; |
1515 | 0 | break; |
1516 | 0 | case PROTO_TCP: |
1517 | 0 | *s = s_tcp; |
1518 | 0 | break; |
1519 | 0 | case PROTO_TLS: |
1520 | 0 | *s = s_tls; |
1521 | 0 | break; |
1522 | 0 | case PROTO_SCTP: |
1523 | 0 | *s = s_sctp; |
1524 | 0 | break; |
1525 | 0 | case PROTO_WS: |
1526 | 0 | case PROTO_WSS: |
1527 | 0 | *s = s_ws; |
1528 | 0 | break; |
1529 | 0 | default: |
1530 | 0 | *s = s_null; |
1531 | 0 | } |
1532 | 0 | } |