/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 | 28 | { |
47 | 28 | int i = 0; |
48 | | |
49 | 28 | if(_sr_uri_host_extra_chars == NULL |
50 | 28 | || _sr_uri_host_extra_chars[0] == '\0') { |
51 | 28 | return 0; |
52 | 28 | } |
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.73k | { |
68 | 8.73k | enum states |
69 | 8.73k | { |
70 | 8.73k | URI_INIT, |
71 | 8.73k | URI_USER, |
72 | 8.73k | URI_PASSWORD, |
73 | 8.73k | URI_PASSWORD_ALPHA, |
74 | 8.73k | URI_HOST, |
75 | 8.73k | URI_HOST_P, |
76 | 8.73k | URI_HOST6_P, |
77 | 8.73k | URI_HOST6_END, |
78 | 8.73k | URI_PORT, |
79 | 8.73k | URI_PARAM, |
80 | 8.73k | URI_PARAM_P, |
81 | 8.73k | URI_VAL_P, |
82 | 8.73k | URI_HEADERS, |
83 | | /* param states */ |
84 | | /* transport */ |
85 | 8.73k | PT_T, |
86 | 8.73k | PT_R, |
87 | 8.73k | PT_A, |
88 | 8.73k | PT_N, |
89 | 8.73k | PT_S, |
90 | 8.73k | PT_P, |
91 | 8.73k | PT_O, |
92 | 8.73k | PT_R2, |
93 | 8.73k | PT_T2, |
94 | 8.73k | PT_eq, |
95 | | /* ttl */ |
96 | 8.73k | PTTL_T2, |
97 | 8.73k | PTTL_L, |
98 | 8.73k | PTTL_eq, |
99 | | /* user */ |
100 | 8.73k | PU_U, |
101 | 8.73k | PU_S, |
102 | 8.73k | PU_E, |
103 | 8.73k | PU_R, |
104 | 8.73k | PU_eq, |
105 | | /* method */ |
106 | 8.73k | PM_M, |
107 | 8.73k | PM_E, |
108 | 8.73k | PM_T, |
109 | 8.73k | PM_H, |
110 | 8.73k | PM_O, |
111 | 8.73k | PM_D, |
112 | 8.73k | PM_eq, |
113 | | /* maddr */ |
114 | 8.73k | PMA_A, |
115 | 8.73k | PMA_D, |
116 | 8.73k | PMA_D2, |
117 | 8.73k | PMA_R, |
118 | 8.73k | PMA_eq, |
119 | | /* lr */ |
120 | 8.73k | PLR_L, |
121 | 8.73k | PLR_R_FIN, |
122 | 8.73k | PLR_eq, |
123 | | /* r2 */ |
124 | 8.73k | PR2_R, |
125 | 8.73k | PR2_2_FIN, |
126 | 8.73k | PR2_eq, |
127 | | /* gr */ |
128 | 8.73k | PGR_G, |
129 | 8.73k | PGR_R_FIN, |
130 | 8.73k | 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.73k | VU_U, |
158 | 8.73k | VU_D, |
159 | 8.73k | VU_P_FIN, |
160 | | /* tcp */ |
161 | 8.73k | VT_T, |
162 | 8.73k | VT_C, |
163 | 8.73k | VT_P_FIN, |
164 | | /* tls */ |
165 | 8.73k | VTLS_L, |
166 | 8.73k | VTLS_S_FIN, |
167 | | /* sctp */ |
168 | 8.73k | VS_S, |
169 | 8.73k | VS_C, |
170 | 8.73k | VS_T, |
171 | 8.73k | VS_P_FIN, |
172 | | /* ws */ |
173 | 8.73k | VW_W, |
174 | 8.73k | VW_S_FIN |
175 | 8.73k | }; |
176 | 8.73k | register enum states state; |
177 | 8.73k | char *s; |
178 | 8.73k | char *b; /* param start */ |
179 | 8.73k | char *v; /* value start */ |
180 | 8.73k | str *param; /* current param */ |
181 | 8.73k | str *param_val; /* current param val */ |
182 | 8.73k | str user; |
183 | 8.73k | str password; |
184 | 8.73k | int port_no; |
185 | 8.73k | register char *p; |
186 | 8.73k | char *end; |
187 | 8.73k | char *pass; |
188 | 8.73k | int found_user; |
189 | 8.73k | int error_headers; |
190 | 8.73k | uint32_t scheme; |
191 | 8.73k | uri_type backup_urit; |
192 | 8.73k | 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.73k | #define SIP_SCH 0x3a706973 |
200 | 8.73k | #define SIPS_SCH 0x73706973 |
201 | 8.73k | #define TEL_SCH 0x3a6c6574 |
202 | 8.73k | #define URN_SCH 0x3a6e7275 |
203 | | |
204 | 8.73k | #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.73k | #define still_at_user \ |
213 | 8.73k | if(found_user == 0) { \ |
214 | 1.00k | user.s = uri->host.s; \ |
215 | 1.00k | if(pass) { \ |
216 | 451 | user.len = pass - user.s; \ |
217 | 451 | password.s = pass + 1; \ |
218 | 451 | password.len = p - password.s; \ |
219 | 555 | } else { \ |
220 | 555 | user.len = p - user.s; \ |
221 | 555 | } \ |
222 | | /* save the uri type/scheme */ \ |
223 | 1.00k | backup_urit = uri->type; \ |
224 | 1.00k | backup_urif = uri->flags; \ |
225 | | /* everything else is 0 */ \ |
226 | 1.00k | memset(uri, 0, sizeof(struct sip_uri)); \ |
227 | | /* restore the scheme & flags, copy user & pass */ \ |
228 | 1.00k | uri->type = backup_urit; \ |
229 | 1.00k | uri->flags = backup_urif; \ |
230 | 1.00k | uri->user = user; \ |
231 | 1.00k | if(pass) \ |
232 | 1.00k | uri->passwd = password; \ |
233 | 1.00k | s = p + 1; \ |
234 | 1.00k | found_user = 1; \ |
235 | 1.00k | error_headers = 0; \ |
236 | 1.00k | state = URI_HOST; \ |
237 | 1.00k | } else \ |
238 | 1.24k | goto error_bad_char |
239 | | |
240 | 8.73k | #define check_host_end \ |
241 | 8.73k | case ':': \ |
242 | | /* found the host */ \ |
243 | 618 | uri->host.s = s; \ |
244 | 618 | uri->host.len = p - s; \ |
245 | 618 | state = URI_PORT; \ |
246 | 618 | s = p + 1; \ |
247 | 618 | break; \ |
248 | 820 | case ';': \ |
249 | 820 | uri->host.s = s; \ |
250 | 820 | uri->host.len = p - s; \ |
251 | 820 | state = URI_PARAM; \ |
252 | 820 | s = p + 1; \ |
253 | 820 | break; \ |
254 | 820 | 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 | 17 | case '@': \ |
262 | 17 | goto error_bad_char |
263 | | |
264 | | |
265 | 8.73k | #define param_set(t_start, v_start) \ |
266 | 38.9k | param->s = (t_start); \ |
267 | 38.9k | param->len = (p - (t_start)); \ |
268 | 38.9k | param_val->s = (v_start); \ |
269 | 38.9k | param_val->len = (p - (v_start)) |
270 | | |
271 | 8.73k | #define semicolon_case \ |
272 | 142k | case ';': \ |
273 | 142k | if(pass) { \ |
274 | 268 | found_user = 1; /* no user, pass cannot contain ';'*/ \ |
275 | 268 | pass = 0; \ |
276 | 268 | } \ |
277 | 142k | state = URI_PARAM /* new param */ |
278 | | |
279 | 8.73k | #define question_case \ |
280 | 8.73k | case '?': \ |
281 | 965 | uri->params.s = s; \ |
282 | 965 | uri->params.len = p - s; \ |
283 | 965 | state = URI_HEADERS; \ |
284 | 965 | s = p + 1; \ |
285 | 965 | if(pass) { \ |
286 | 225 | found_user = 1; /* no user, pass cannot contain '?'*/ \ |
287 | 225 | pass = 0; \ |
288 | 225 | } |
289 | | |
290 | 8.73k | #define colon_case \ |
291 | 34.4k | case ':': \ |
292 | 34.4k | if(found_user == 0) { \ |
293 | | /*might be pass but only if user not found yet*/ \ |
294 | 732 | if(pass) { \ |
295 | 37 | found_user = 1; /* no user */ \ |
296 | 37 | pass = 0; \ |
297 | 695 | } else { \ |
298 | 695 | pass = p; \ |
299 | 695 | } \ |
300 | 732 | } \ |
301 | 34.4k | state = URI_PARAM_P /* generic param */ |
302 | | |
303 | 8.73k | #define param_common_cases \ |
304 | 8.73k | case '@': \ |
305 | | /* ughhh, this is still the user */ \ |
306 | 702 | still_at_user; \ |
307 | 541 | break; \ |
308 | 92.2k | semicolon_case; \ |
309 | 92.2k | break; \ |
310 | 92.2k | question_case; \ |
311 | 655 | break; \ |
312 | 24.7k | colon_case; \ |
313 | 24.7k | break |
314 | | |
315 | 8.73k | #define value_common_cases \ |
316 | 8.73k | case '@': \ |
317 | | /* ughhh, this is still the user */ \ |
318 | 87 | still_at_user; \ |
319 | 46 | break; \ |
320 | 32.1k | semicolon_case; \ |
321 | 32.1k | param_set(b, v); \ |
322 | 32.1k | break; \ |
323 | 32.1k | question_case; \ |
324 | 174 | param_set(b, v); \ |
325 | 174 | break; \ |
326 | 5.74k | colon_case; \ |
327 | 5.74k | state = URI_VAL_P; \ |
328 | 5.74k | break |
329 | | |
330 | 8.73k | #define param_switch(old_state, c1, c2, new_state) \ |
331 | 496k | case old_state: \ |
332 | 496k | switch(*p) { \ |
333 | 270k | case c1: \ |
334 | 448k | case c2: \ |
335 | 448k | state = (new_state); \ |
336 | 448k | break; \ |
337 | 270k | param_common_cases; \ |
338 | 16.7k | default: \ |
339 | 16.7k | state = URI_PARAM_P; \ |
340 | 496k | } \ |
341 | 496k | break |
342 | 8.73k | #define param_switch1(old_state, c1, new_state) \ |
343 | 68.3k | case old_state: \ |
344 | 68.3k | switch(*p) { \ |
345 | 54.0k | case c1: \ |
346 | 54.0k | state = (new_state); \ |
347 | 54.0k | break; \ |
348 | 48 | param_common_cases; \ |
349 | 4.10k | default: \ |
350 | 4.10k | state = URI_PARAM_P; \ |
351 | 68.3k | } \ |
352 | 68.3k | break |
353 | 8.73k | #define param_switch_big(old_state, c1, c2, d1, d2, new_state_c, new_state_d) \ |
354 | 96.3k | case old_state: \ |
355 | 96.3k | switch(*p) { \ |
356 | 59.5k | case c1: \ |
357 | 71.6k | case c2: \ |
358 | 71.6k | state = (new_state_c); \ |
359 | 71.6k | break; \ |
360 | 59.5k | case d1: \ |
361 | 18.1k | case d2: \ |
362 | 18.1k | state = (new_state_d); \ |
363 | 18.1k | break; \ |
364 | 9.59k | param_common_cases; \ |
365 | 2.66k | default: \ |
366 | 2.66k | state = URI_PARAM_P; \ |
367 | 96.3k | } \ |
368 | 96.3k | break |
369 | 8.73k | #define value_switch(old_state, c1, c2, new_state) \ |
370 | 49.3k | case old_state: \ |
371 | 49.3k | switch(*p) { \ |
372 | 20.6k | case c1: \ |
373 | 33.6k | case c2: \ |
374 | 33.6k | state = (new_state); \ |
375 | 33.6k | break; \ |
376 | 20.6k | value_common_cases; \ |
377 | 3.86k | default: \ |
378 | 3.86k | state = URI_VAL_P; \ |
379 | 49.3k | } \ |
380 | 49.3k | break |
381 | 8.73k | #define value_switch_big(old_state, c1, c2, d1, d2, new_state_c, new_state_d) \ |
382 | 11.6k | case old_state: \ |
383 | 11.6k | switch(*p) { \ |
384 | 1.58k | case c1: \ |
385 | 4.03k | case c2: \ |
386 | 4.03k | state = (new_state_c); \ |
387 | 4.03k | break; \ |
388 | 1.58k | case d1: \ |
389 | 4.69k | case d2: \ |
390 | 4.69k | state = (new_state_d); \ |
391 | 4.69k | break; \ |
392 | 1.32k | value_common_cases; \ |
393 | 739 | default: \ |
394 | 739 | state = URI_VAL_P; \ |
395 | 11.6k | } \ |
396 | 11.6k | break |
397 | | |
398 | 8.73k | #define transport_fin(c_state, proto_no) \ |
399 | 13.7k | case c_state: \ |
400 | 13.7k | switch(*p) { \ |
401 | 40 | case '@': \ |
402 | 40 | still_at_user; \ |
403 | 40 | break; \ |
404 | 5.32k | semicolon_case; \ |
405 | 5.32k | param_set(b, v); \ |
406 | 5.32k | uri->proto = (proto_no); \ |
407 | 5.32k | break; \ |
408 | 85 | question_case; \ |
409 | 85 | param_set(b, v); \ |
410 | 85 | uri->proto = (proto_no); \ |
411 | 85 | break; \ |
412 | 2.69k | colon_case; \ |
413 | 8.27k | default: \ |
414 | 8.27k | state = URI_VAL_P; \ |
415 | 8.27k | break; \ |
416 | 13.7k | } \ |
417 | 13.7k | 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.73k | end = buf + len; |
446 | 8.73k | p = buf + 4; |
447 | 8.73k | found_user = 0; |
448 | 8.73k | error_headers = 0; |
449 | 8.73k | b = v = 0; |
450 | 8.73k | param = param_val = 0; |
451 | 8.73k | pass = 0; |
452 | 8.73k | password.s = 0; /* fixes gcc 4.0 warning */ |
453 | 8.73k | password.len = 0; |
454 | 8.73k | port_no = 0; |
455 | 8.73k | state = URI_INIT; |
456 | 8.73k | memset(uri, 0, sizeof(struct sip_uri)); /* zero it all, just to be sure*/ |
457 | | /*look for sip:, sips:, tel: or urn:*/ |
458 | 8.73k | if(len < 5) |
459 | 889 | goto error_too_short; |
460 | 7.84k | scheme = ((uint32_t)buf[0]) + (((uint32_t)buf[1]) << 8) |
461 | 7.84k | + (((uint32_t)buf[2]) << 16) + (((uint32_t)buf[3]) << 24); |
462 | 7.84k | scheme |= 0x20202020; |
463 | 7.84k | if(scheme == SIP_SCH) { |
464 | 2.50k | uri->type = SIP_URI_T; |
465 | 5.34k | } else if(scheme == SIPS_SCH) { |
466 | 26 | if(buf[4] == ':') { |
467 | 11 | p++; |
468 | 11 | uri->type = SIPS_URI_T; |
469 | 11 | } else |
470 | 15 | goto error_bad_uri; |
471 | 5.31k | } else if(scheme == TEL_SCH) { |
472 | 3.65k | uri->type = TEL_URI_T; |
473 | 3.65k | } else if(scheme == URN_SCH) { |
474 | 1.41k | uri->type = URN_URI_T; |
475 | 1.41k | } else |
476 | 248 | goto error_bad_uri; |
477 | | |
478 | 7.58k | s = p; |
479 | 3.11M | for(; p < end; p++) { |
480 | 3.10M | switch((unsigned char)state) { |
481 | 7.58k | case URI_INIT: |
482 | 7.58k | switch(*p) { |
483 | 667 | case '[': |
484 | | /* uri = [ipv6address]... */ |
485 | 667 | state = URI_HOST6_P; |
486 | 667 | s = p; |
487 | 667 | 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 | 77 | case '@': /* error no user part, or |
494 | | * be forgiving and accept it ? */ |
495 | 6.90k | default: |
496 | 6.90k | state = URI_USER; |
497 | 7.58k | } |
498 | 7.57k | break; |
499 | 1.17M | case URI_USER: |
500 | 1.17M | switch(*p) { |
501 | 215 | case '@': |
502 | | /* found the user*/ |
503 | 215 | uri->user.s = s; |
504 | 215 | uri->user.len = p - s; |
505 | 215 | if(uri->user.len <= 0) { |
506 | | /* at '@' and no user part */ |
507 | 0 | goto error_bad_char; |
508 | 0 | } |
509 | 215 | state = URI_HOST; |
510 | 215 | found_user = 1; |
511 | 215 | s = p + 1; /* skip '@' */ |
512 | 215 | break; |
513 | 1.72k | case ':': |
514 | | /* found the user, or the host? */ |
515 | 1.72k | uri->user.s = s; |
516 | 1.72k | uri->user.len = p - s; |
517 | 1.72k | state = URI_PASSWORD; |
518 | 1.72k | s = p + 1; /* skip ':' */ |
519 | 1.72k | break; |
520 | 4.68k | case ';': |
521 | | /* this could be still the user or |
522 | | * params?*/ |
523 | 4.68k | uri->host.s = s; |
524 | 4.68k | uri->host.len = p - s; |
525 | 4.68k | state = URI_PARAM; |
526 | 4.68k | s = p + 1; |
527 | 4.68k | break; |
528 | 157 | case '?': /* still user or headers? */ |
529 | 157 | uri->host.s = s; |
530 | 157 | uri->host.len = p - s; |
531 | 157 | state = URI_HEADERS; |
532 | 157 | s = p + 1; |
533 | 157 | break; |
534 | | /* almost anything permitted in the user part */ |
535 | 7.27k | case '.': |
536 | 61.5k | case '-': |
537 | 68.5k | case '(': |
538 | 70.6k | case ')': |
539 | | /* tel uri visual separators, set flag meaning, that |
540 | | * user should be normalized before usage |
541 | | */ |
542 | 70.6k | uri->flags |= URI_USER_NORMALIZE; |
543 | 70.6k | break; |
544 | 4 | case '[': |
545 | 8 | case ']': /* the user part cannot contain "[]" */ |
546 | 8 | goto error_bad_char; |
547 | 1.17M | } |
548 | 1.17M | break; |
549 | 1.17M | case URI_PASSWORD: /* this can also be the port (missing user)*/ |
550 | 69.2k | switch(*p) { |
551 | 5 | case '@': |
552 | | /* found the password*/ |
553 | 5 | uri->passwd.s = s; |
554 | 5 | uri->passwd.len = p - s; |
555 | 5 | port_no = 0; |
556 | 5 | state = URI_HOST; |
557 | 5 | found_user = 1; |
558 | 5 | s = p + 1; /* skip '@' */ |
559 | 5 | break; |
560 | 1.10k | case ';': |
561 | | /* upps this is the port */ |
562 | 1.10k | uri->port.s = s; |
563 | 1.10k | uri->port.len = p - s; |
564 | 1.10k | uri->port_no = port_no; |
565 | | /* user contains in fact the host */ |
566 | 1.10k | uri->host.s = uri->user.s; |
567 | 1.10k | uri->host.len = uri->user.len; |
568 | 1.10k | uri->user.s = 0; |
569 | 1.10k | uri->user.len = 0; |
570 | 1.10k | state = URI_PARAM; |
571 | 1.10k | found_user = 1; /* there is no user part */ |
572 | 1.10k | s = p + 1; |
573 | 1.10k | break; |
574 | 25 | case '?': |
575 | | /* upps this is the port */ |
576 | 25 | uri->port.s = s; |
577 | 25 | uri->port.len = p - s; |
578 | 25 | uri->port_no = port_no; |
579 | | /* user contains in fact the host */ |
580 | 25 | uri->host.s = uri->user.s; |
581 | 25 | uri->host.len = uri->user.len; |
582 | 25 | uri->user.s = 0; |
583 | 25 | uri->user.len = 0; |
584 | 25 | state = URI_HEADERS; |
585 | 25 | found_user = 1; /* there is no user part */ |
586 | 25 | s = p + 1; |
587 | 25 | break; |
588 | 66.0k | case_port('0', port_no); |
589 | 65.9k | case_port('1', port_no); |
590 | 177 | case_port('2', port_no); |
591 | 196 | case_port('3', port_no); |
592 | 231 | case_port('4', port_no); |
593 | 409 | case_port('5', port_no); |
594 | 398 | case_port('6', port_no); |
595 | 350 | case_port('7', port_no); |
596 | 177 | case_port('8', port_no); |
597 | 172 | case_port('9', port_no); |
598 | 163 | case '[': |
599 | 8 | case ']': |
600 | 12 | case ':': |
601 | 12 | goto error_bad_char; |
602 | 57 | default: |
603 | | /* it can't be the port, non number found */ |
604 | 57 | port_no = 0; |
605 | 57 | state = URI_PASSWORD_ALPHA; |
606 | 69.2k | } |
607 | 69.1k | break; |
608 | 69.1k | case URI_PASSWORD_ALPHA: |
609 | 416 | 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 | 9 | case ']': |
623 | 13 | case ':': |
624 | 13 | goto error_bad_char; |
625 | 416 | } |
626 | 395 | break; |
627 | 968 | case URI_HOST: |
628 | 968 | if(*p == '[') { |
629 | 22 | state = URI_HOST6_P; |
630 | 946 | } else { |
631 | 946 | if(isalnum(*p)) { |
632 | 936 | state = URI_HOST_P; |
633 | 936 | } else { |
634 | 10 | goto error_bad_host; |
635 | 10 | } |
636 | 946 | } |
637 | 958 | break; |
638 | 2.05k | case URI_HOST_P: |
639 | 2.05k | switch(*p) { |
640 | 22 | check_host_end; |
641 | 1.21k | default: |
642 | 1.21k | if(!isalnum(*p) && (*p != '.') && (*p != '-') |
643 | 1.21k | && !uri_host_char_allowed(*p)) { |
644 | 28 | goto error_bad_host; |
645 | 28 | } |
646 | 2.05k | } |
647 | 2.01k | break; |
648 | 2.01k | case URI_HOST6_END: |
649 | 639 | switch(*p) { |
650 | 596 | check_host_end; |
651 | 5 | default: /*no chars allowed after [ipv6] */ |
652 | 5 | goto error_bad_host; |
653 | 639 | } |
654 | 626 | break; |
655 | 1.06k | case URI_HOST6_P: |
656 | 1.06k | switch(*p) { |
657 | 647 | case ']': |
658 | 647 | state = URI_HOST6_END; |
659 | 647 | break; |
660 | 4 | case '[': |
661 | 8 | case '&': |
662 | 12 | case '@': |
663 | 17 | case ';': |
664 | 21 | case '?': |
665 | 21 | goto error_bad_host; |
666 | 1.06k | } |
667 | 1.04k | break; |
668 | 2.82k | case URI_PORT: |
669 | 2.82k | switch(*p) { |
670 | 15 | case ';': |
671 | 15 | uri->port.s = s; |
672 | 15 | uri->port.len = p - s; |
673 | 15 | uri->port_no = port_no; |
674 | 15 | state = URI_PARAM; |
675 | 15 | s = p + 1; |
676 | 15 | break; |
677 | 17 | case '?': |
678 | 17 | uri->port.s = s; |
679 | 17 | uri->port.len = p - s; |
680 | 17 | uri->port_no = port_no; |
681 | 17 | state = URI_HEADERS; |
682 | 17 | s = p + 1; |
683 | 17 | break; |
684 | 528 | case_port('0', port_no); |
685 | 519 | case_port('1', port_no); |
686 | 195 | case_port('2', port_no); |
687 | 213 | case_port('3', port_no); |
688 | 256 | case_port('4', port_no); |
689 | 416 | case_port('5', port_no); |
690 | 407 | case_port('6', port_no); |
691 | 372 | case_port('7', port_no); |
692 | 202 | case_port('8', port_no); |
693 | 186 | case_port('9', port_no); |
694 | 177 | case '&': |
695 | 0 | case '@': |
696 | 2 | case ':': |
697 | 8 | default: |
698 | 8 | goto error_bad_port; |
699 | 2.82k | } |
700 | 2.72k | break; |
701 | 147k | case URI_PARAM: /* beginning of a new param */ |
702 | 147k | switch(*p) { |
703 | 27 | param_common_cases; |
704 | | /* recognized params */ |
705 | 29.5k | case 't': |
706 | 73.4k | case 'T': |
707 | 73.4k | b = p; |
708 | 73.4k | state = PT_T; |
709 | 73.4k | break; |
710 | 6.49k | case 'u': |
711 | 16.1k | case 'U': |
712 | 16.1k | b = p; |
713 | 16.1k | state = PU_U; |
714 | 16.1k | break; |
715 | 12.2k | case 'm': |
716 | 22.9k | case 'M': |
717 | 22.9k | b = p; |
718 | 22.9k | state = PM_M; |
719 | 22.9k | break; |
720 | 8.65k | case 'l': |
721 | 10.6k | case 'L': |
722 | 10.6k | b = p; |
723 | 10.6k | state = PLR_L; |
724 | 10.6k | break; |
725 | 2.60k | case 'r': |
726 | 5.28k | case 'R': |
727 | 5.28k | b = p; |
728 | 5.28k | state = PR2_R; |
729 | 5.28k | break; |
730 | 8.44k | case 'g': |
731 | 13.0k | case 'G': |
732 | 13.0k | b = p; |
733 | 13.0k | state = PGR_G; |
734 | 13.0k | break; |
735 | | #ifdef USE_COMP |
736 | | case 'c': |
737 | | case 'C': |
738 | | b = p; |
739 | | state = PCOMP_C; |
740 | | break; |
741 | | #endif |
742 | 3.29k | default: |
743 | 3.29k | state = URI_PARAM_P; |
744 | 147k | } |
745 | 147k | break; |
746 | 429k | case URI_PARAM_P: /* ignore current param */ |
747 | | /* supported params: |
748 | | * maddr, transport, ttl, lr, user, method, r2 */ |
749 | 429k | switch(*p) { |
750 | 429k | param_common_cases; |
751 | 429k | }; |
752 | 429k | break; |
753 | | /* ugly but fast param names parsing */ |
754 | | /*transport */ |
755 | 73.4k | param_switch_big(PT_T, 'r', 'R', 't', 'T', PT_R, PTTL_T2); |
756 | 73.4k | param_switch(PT_R, 'a', 'A', PT_A); |
757 | 60.0k | param_switch(PT_A, 'n', 'N', PT_N); |
758 | 57.8k | param_switch(PT_N, 's', 'S', PT_S); |
759 | 55.4k | param_switch(PT_S, 'p', 'P', PT_P); |
760 | 53.2k | param_switch(PT_P, 'o', 'O', PT_O); |
761 | 51.1k | param_switch(PT_O, 'r', 'R', PT_R2); |
762 | 47.9k | param_switch(PT_R2, 't', 'T', PT_T2); |
763 | 45.8k | param_switch1(PT_T2, '=', PT_eq); |
764 | | /* value parsing */ |
765 | 43.2k | case PT_eq: |
766 | 41.1k | param = &uri->transport; |
767 | 41.1k | param_val = &uri->transport_val; |
768 | 41.1k | switch(*p) { |
769 | 8 | param_common_cases; |
770 | 2.07k | case 'u': |
771 | 5.50k | case 'U': |
772 | 5.50k | v = p; |
773 | 5.50k | state = VU_U; |
774 | 5.50k | break; |
775 | 5.30k | case 't': |
776 | 11.6k | case 'T': |
777 | 11.6k | v = p; |
778 | 11.6k | state = VT_T; |
779 | 11.6k | break; |
780 | 7.50k | case 's': |
781 | 11.1k | case 'S': |
782 | 11.1k | v = p; |
783 | 11.1k | state = VS_S; |
784 | 11.1k | break; |
785 | 2.42k | case 'w': |
786 | 4.40k | case 'W': |
787 | 4.40k | v = p; |
788 | 4.40k | state = VW_W; |
789 | 4.40k | break; |
790 | 576 | default: |
791 | 576 | v = p; |
792 | 576 | state = URI_VAL_P; |
793 | 41.1k | } |
794 | 41.1k | break; |
795 | | /* generic value */ |
796 | 461k | case URI_VAL_P: |
797 | 461k | switch(*p) { |
798 | 461k | value_common_cases; |
799 | 461k | } |
800 | 461k | break; |
801 | | /* udp */ |
802 | 461k | value_switch(VU_U, 'd', 'D', VU_D); |
803 | 5.47k | value_switch(VU_D, 'p', 'P', VU_P_FIN); |
804 | 3.83k | transport_fin(VU_P_FIN, PROTO_UDP); |
805 | | /* tcp */ |
806 | 11.6k | value_switch_big(VT_T, 'c', 'C', 'l', 'L', VT_C, VTLS_L); |
807 | 11.6k | value_switch(VT_C, 'p', 'P', VT_P_FIN); |
808 | 3.99k | transport_fin(VT_P_FIN, PROTO_TCP); |
809 | | /* tls */ |
810 | 4.66k | value_switch(VTLS_L, 's', 'S', VTLS_S_FIN); |
811 | 4.66k | transport_fin(VTLS_S_FIN, PROTO_TLS); |
812 | | /* sctp */ |
813 | 11.1k | value_switch(VS_S, 'c', 'C', VS_C); |
814 | 11.1k | value_switch(VS_C, 't', 'T', VS_T); |
815 | 8.90k | value_switch(VS_T, 'p', 'P', VS_P_FIN); |
816 | 6.92k | transport_fin(VS_P_FIN, PROTO_SCTP); |
817 | | /* ws */ |
818 | 5.22k | value_switch(VW_W, 's', 'S', VW_S_FIN); |
819 | 4.37k | transport_fin(VW_S_FIN, PROTO_WS); |
820 | | |
821 | | /* ttl */ |
822 | 9.57k | param_switch(PTTL_T2, 'l', 'L', PTTL_L); |
823 | 9.57k | param_switch1(PTTL_L, '=', PTTL_eq); |
824 | 7.30k | case PTTL_eq: |
825 | 3.71k | param = &uri->ttl; |
826 | 3.71k | param_val = &uri->ttl_val; |
827 | 3.71k | switch(*p) { |
828 | 8 | param_common_cases; |
829 | 2.65k | default: |
830 | 2.65k | v = p; |
831 | 2.65k | state = URI_VAL_P; |
832 | 3.71k | } |
833 | 3.70k | break; |
834 | | |
835 | | /* user param */ |
836 | 16.1k | param_switch(PU_U, 's', 'S', PU_S); |
837 | 16.1k | param_switch(PU_S, 'e', 'E', PU_E); |
838 | 13.8k | param_switch(PU_E, 'r', 'R', PU_R); |
839 | 8.17k | param_switch1(PU_R, '=', PU_eq); |
840 | 6.02k | case PU_eq: |
841 | 3.46k | param = &uri->user_param; |
842 | 3.46k | param_val = &uri->user_param_val; |
843 | 3.46k | switch(*p) { |
844 | 8 | param_common_cases; |
845 | 693 | default: |
846 | 693 | v = p; |
847 | 693 | state = URI_VAL_P; |
848 | 3.46k | } |
849 | 3.45k | break; |
850 | | |
851 | | /* method*/ |
852 | 22.8k | param_switch_big(PM_M, 'e', 'E', 'a', 'A', PM_E, PMA_A); |
853 | 22.8k | param_switch(PM_E, 't', 'T', PM_T); |
854 | 11.5k | param_switch(PM_T, 'h', 'H', PM_H); |
855 | 9.56k | param_switch(PM_H, 'o', 'O', PM_O); |
856 | 7.16k | param_switch(PM_O, 'd', 'D', PM_D); |
857 | 5.35k | param_switch1(PM_D, '=', PM_eq); |
858 | 3.47k | case PM_eq: |
859 | 1.46k | param = &uri->method; |
860 | 1.46k | param_val = &uri->method_val; |
861 | 1.46k | switch(*p) { |
862 | 8 | param_common_cases; |
863 | 403 | default: |
864 | 403 | v = p; |
865 | 403 | state = URI_VAL_P; |
866 | 1.46k | } |
867 | 1.46k | break; |
868 | | |
869 | | /*maddr*/ |
870 | 8.50k | param_switch(PMA_A, 'd', 'D', PMA_D); |
871 | 8.50k | param_switch(PMA_D, 'd', 'D', PMA_D2); |
872 | 6.79k | param_switch(PMA_D2, 'r', 'R', PMA_R); |
873 | 4.92k | param_switch1(PMA_R, '=', PMA_eq); |
874 | 3.09k | case PMA_eq: |
875 | 1.38k | param = &uri->maddr; |
876 | 1.38k | param_val = &uri->maddr_val; |
877 | 1.38k | switch(*p) { |
878 | 8 | param_common_cases; |
879 | 388 | default: |
880 | 388 | v = p; |
881 | 388 | state = URI_VAL_P; |
882 | 1.38k | } |
883 | 1.37k | break; |
884 | | |
885 | | /* lr */ |
886 | 10.6k | param_switch(PLR_L, 'r', 'R', PLR_R_FIN); |
887 | 10.6k | case PLR_R_FIN: |
888 | 8.25k | switch(*p) { |
889 | 8 | case '@': |
890 | 8 | still_at_user; |
891 | 4 | break; |
892 | 1.47k | case '=': |
893 | 1.47k | state = PLR_eq; |
894 | 1.47k | break; |
895 | 5.63k | semicolon_case; |
896 | 5.63k | uri->lr.s = b; |
897 | 5.63k | uri->lr.len = (p - b); |
898 | 5.63k | break; |
899 | 17 | question_case; |
900 | 17 | uri->lr.s = b; |
901 | 17 | uri->lr.len = (p - b); |
902 | 17 | break; |
903 | 489 | colon_case; |
904 | 489 | break; |
905 | 640 | default: |
906 | 640 | state = URI_PARAM_P; |
907 | 8.25k | } |
908 | 8.25k | break; |
909 | | /* handle lr=something case */ |
910 | 8.25k | case PLR_eq: |
911 | 1.46k | param = &uri->lr; |
912 | 1.46k | param_val = &uri->lr_val; |
913 | 1.46k | switch(*p) { |
914 | 10 | param_common_cases; |
915 | 587 | default: |
916 | 587 | v = p; |
917 | 587 | state = URI_VAL_P; |
918 | 1.46k | } |
919 | 1.45k | break; |
920 | | /* r2 */ |
921 | 5.25k | param_switch1(PR2_R, '2', PR2_2_FIN); |
922 | 5.25k | case PR2_2_FIN: |
923 | 2.85k | switch(*p) { |
924 | 8 | case '@': |
925 | 8 | still_at_user; |
926 | 4 | break; |
927 | 1.42k | case '=': |
928 | 1.42k | state = PR2_eq; |
929 | 1.42k | break; |
930 | 582 | semicolon_case; |
931 | 582 | uri->r2.s = b; |
932 | 582 | uri->r2.len = (p - b); |
933 | 582 | break; |
934 | 17 | question_case; |
935 | 17 | uri->r2.s = b; |
936 | 17 | uri->r2.len = (p - b); |
937 | 17 | break; |
938 | 411 | colon_case; |
939 | 411 | break; |
940 | 410 | default: |
941 | 410 | state = URI_PARAM_P; |
942 | 2.85k | } |
943 | 2.84k | break; |
944 | | /* handle lr=something case */ |
945 | 2.84k | case PR2_eq: |
946 | 1.40k | param = &uri->r2; |
947 | 1.40k | param_val = &uri->r2_val; |
948 | 1.40k | switch(*p) { |
949 | 8 | param_common_cases; |
950 | 441 | default: |
951 | 441 | v = p; |
952 | 441 | state = URI_VAL_P; |
953 | 1.40k | } |
954 | 1.40k | break; |
955 | | /* gr */ |
956 | 13.0k | param_switch(PGR_G, 'r', 'R', PGR_R_FIN); |
957 | 13.0k | case PGR_R_FIN: |
958 | 8.77k | switch(*p) { |
959 | 8 | case '@': |
960 | 8 | still_at_user; |
961 | 4 | break; |
962 | 1.49k | case '=': |
963 | 1.49k | state = PGR_eq; |
964 | 1.49k | break; |
965 | 6.27k | semicolon_case; |
966 | 6.27k | uri->gr.s = b; |
967 | 6.27k | uri->gr.len = (p - b); |
968 | 6.27k | 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 | 581 | default: |
976 | 581 | state = URI_PARAM_P; |
977 | 8.77k | } |
978 | 8.76k | break; |
979 | | /* handle gr=something case */ |
980 | 8.76k | case PGR_eq: |
981 | 1.48k | param = &uri->gr; |
982 | 1.48k | param_val = &uri->gr_val; |
983 | 1.48k | switch(*p) { |
984 | 8 | param_common_cases; |
985 | 586 | default: |
986 | 586 | v = p; |
987 | 586 | state = URI_VAL_P; |
988 | 1.48k | } |
989 | 1.47k | 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 | 2.43k | 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 | 2.43k | switch(*p) { |
1034 | 392 | case '@': |
1035 | | /* yak, we are still at user */ |
1036 | 392 | still_at_user; |
1037 | 387 | break; |
1038 | 402 | case ';': |
1039 | | /* we might be still parsing user, try it */ |
1040 | 402 | if(found_user) |
1041 | 8 | goto error_bad_char; |
1042 | 394 | 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 | 394 | if(pass) |
1047 | 4 | goto error_headers; |
1048 | 390 | break; |
1049 | 496 | case ':': |
1050 | 496 | if(found_user == 0) { |
1051 | | /*might be pass but only if user not found yet*/ |
1052 | 106 | if(pass) { |
1053 | 6 | found_user = 1; /* no user */ |
1054 | 6 | pass = 0; |
1055 | 100 | } else { |
1056 | 100 | pass = p; |
1057 | 100 | } |
1058 | 106 | } |
1059 | 496 | break; |
1060 | 392 | case '?': |
1061 | 392 | if(pass) { |
1062 | 4 | found_user = |
1063 | 4 | 1; /* no user, pass cannot contain '?'*/ |
1064 | 4 | pass = 0; |
1065 | 4 | } |
1066 | 392 | break; |
1067 | 2.43k | } |
1068 | 2.41k | break; |
1069 | 2.41k | default: |
1070 | 0 | goto error_bug; |
1071 | 3.10M | } |
1072 | 3.10M | } |
1073 | | /*end of uri */ |
1074 | 7.01k | switch(state) { |
1075 | 4 | case URI_INIT: /* error empty uri */ |
1076 | 4 | goto error_too_short; |
1077 | 122 | case URI_USER: |
1078 | | /* this is the host, it can't be the user */ |
1079 | 122 | if(found_user) |
1080 | 0 | goto error_bad_uri; |
1081 | 122 | uri->host.s = s; |
1082 | 122 | uri->host.len = p - s; |
1083 | 122 | state = URI_HOST; |
1084 | 122 | break; |
1085 | 435 | case URI_PASSWORD: |
1086 | | /* this is the port, it can't be the passwd */ |
1087 | 435 | if(found_user) |
1088 | 0 | goto error_bad_port; |
1089 | 435 | uri->port.s = s; |
1090 | 435 | uri->port.len = p - s; |
1091 | 435 | uri->port_no = port_no; |
1092 | 435 | uri->host = uri->user; |
1093 | 435 | uri->user.s = 0; |
1094 | 435 | uri->user.len = 0; |
1095 | 435 | break; |
1096 | 32 | case URI_PASSWORD_ALPHA: |
1097 | | /* it might be an urn, check scheme and set host */ |
1098 | 32 | if(scheme == URN_SCH) { |
1099 | 9 | uri->host.s = s; |
1100 | 9 | uri->host.len = p - s; |
1101 | 9 | LM_DBG("parsed urn scheme with host: %.*s\n", uri->host.len, |
1102 | 9 | uri->host.s); |
1103 | | /* this is the port, it can't be the passwd */ |
1104 | 9 | } else |
1105 | 23 | goto error_bad_port; |
1106 | 9 | break; |
1107 | 67 | case URI_HOST_P: |
1108 | 75 | case URI_HOST6_END: |
1109 | 75 | uri->host.s = s; |
1110 | 75 | uri->host.len = p - s; |
1111 | 75 | break; |
1112 | 262 | case URI_HOST: /* error: null host */ |
1113 | 283 | case URI_HOST6_P: /* error: unterminated ipv6 reference*/ |
1114 | 283 | goto error_bad_host; |
1115 | 484 | case URI_PORT: |
1116 | 484 | uri->port.s = s; |
1117 | 484 | uri->port.len = p - s; |
1118 | 484 | uri->port_no = port_no; |
1119 | 484 | break; |
1120 | 1.13k | case URI_PARAM: |
1121 | 2.53k | case URI_PARAM_P: |
1122 | | /* intermediate param states */ |
1123 | 2.58k | case PT_T: /* transport */ |
1124 | 2.61k | case PT_R: |
1125 | 2.64k | case PT_A: |
1126 | 2.67k | case PT_N: |
1127 | 2.69k | case PT_S: |
1128 | 2.72k | case PT_P: |
1129 | 2.75k | case PT_O: |
1130 | 2.79k | case PT_R2: |
1131 | 2.81k | case PT_T2: |
1132 | 2.82k | case PT_eq: /* ignore empty transport params */ |
1133 | 2.86k | case PTTL_T2: /* ttl */ |
1134 | 2.89k | case PTTL_L: |
1135 | 2.90k | case PTTL_eq: |
1136 | 2.93k | case PU_U: /* user */ |
1137 | 2.97k | case PU_S: |
1138 | 3.00k | case PU_E: |
1139 | 3.03k | case PU_R: |
1140 | 3.04k | case PU_eq: |
1141 | 3.08k | case PM_M: /* method */ |
1142 | 3.11k | case PM_E: |
1143 | 3.14k | case PM_T: |
1144 | 3.17k | case PM_H: |
1145 | 3.20k | case PM_O: |
1146 | 3.23k | case PM_D: |
1147 | 3.25k | case PM_eq: |
1148 | 3.28k | case PLR_L: /* lr */ |
1149 | 3.31k | case PR2_R: /* r2 */ |
1150 | 3.34k | 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.34k | uri->params.s = s; |
1159 | 3.34k | uri->params.len = p - s; |
1160 | 3.34k | break; |
1161 | | /* fin param states */ |
1162 | 29 | 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 | 12 | case PR2_2_FIN: |
1170 | 25 | case PR2_eq: |
1171 | 25 | uri->params.s = s; |
1172 | 25 | uri->params.len = p - s; |
1173 | 25 | uri->r2.s = b; |
1174 | 25 | uri->r2.len = p - b; |
1175 | 25 | break; |
1176 | 30 | case PGR_R_FIN: |
1177 | 45 | case PGR_eq: |
1178 | 45 | uri->params.s = s; |
1179 | 45 | uri->params.len = p - s; |
1180 | 45 | uri->gr.s = b; |
1181 | 45 | uri->gr.len = p - b; |
1182 | 45 | break; |
1183 | 841 | case URI_VAL_P: |
1184 | | /* intermediate value states */ |
1185 | 868 | case VU_U: |
1186 | 896 | case VU_D: |
1187 | 924 | case VT_T: |
1188 | 953 | case VT_C: |
1189 | 983 | case VTLS_L: |
1190 | 1.01k | case VS_S: |
1191 | 1.04k | case VS_C: |
1192 | 1.06k | case VS_T: |
1193 | 1.10k | case VW_W: |
1194 | 1.10k | uri->params.s = s; |
1195 | 1.10k | uri->params.len = p - s; |
1196 | 1.10k | param_set(b, v); |
1197 | 1.10k | 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 | 25 | case VU_P_FIN: |
1216 | 25 | uri->params.s = s; |
1217 | 25 | uri->params.len = p - s; |
1218 | 25 | param_set(b, v); |
1219 | 25 | uri->proto = PROTO_UDP; |
1220 | 25 | break; |
1221 | 25 | case VT_P_FIN: |
1222 | 25 | uri->params.s = s; |
1223 | 25 | uri->params.len = p - s; |
1224 | 25 | param_set(b, v); |
1225 | 25 | uri->proto = PROTO_TCP; |
1226 | 25 | break; |
1227 | 24 | case VTLS_S_FIN: |
1228 | 24 | uri->params.s = s; |
1229 | 24 | uri->params.len = p - s; |
1230 | 24 | param_set(b, v); |
1231 | 24 | uri->proto = PROTO_TLS; |
1232 | 24 | break; |
1233 | 25 | case VS_P_FIN: |
1234 | 25 | uri->params.s = s; |
1235 | 25 | uri->params.len = p - s; |
1236 | 25 | param_set(b, v); |
1237 | 25 | uri->proto = PROTO_SCTP; |
1238 | 25 | break; |
1239 | 26 | case VW_S_FIN: |
1240 | 26 | uri->params.s = s; |
1241 | 26 | uri->params.len = p - s; |
1242 | 26 | param_set(b, v); |
1243 | 26 | uri->proto = PROTO_WS; |
1244 | 26 | 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 | 780 | case URI_HEADERS: |
1261 | 780 | uri->headers.s = s; |
1262 | 780 | uri->headers.len = p - s; |
1263 | 780 | if(error_headers) |
1264 | 18 | goto error_headers; |
1265 | 762 | break; |
1266 | 762 | default: |
1267 | 117 | goto error_bug; |
1268 | 7.01k | } |
1269 | 6.57k | switch(uri->type) { |
1270 | 5 | case SIPS_URI_T: |
1271 | 2.14k | case SIP_URI_T: |
1272 | | /* save the original sip: URI parameters in sip_params */ |
1273 | 2.14k | uri->sip_params = uri->params; |
1274 | 2.14k | if((phone2tel) && (uri->user_param_val.len == 5) |
1275 | 2.14k | && (strncmp(uri->user_param_val.s, "phone", 5) == 0)) { |
1276 | 66 | uri->type = TEL_URI_T; |
1277 | 66 | uri->flags |= URI_SIP_USER_PHONE; |
1278 | | /* move params from user into uri->params */ |
1279 | 66 | p = q_memchr(uri->user.s, ';', uri->user.len); |
1280 | 66 | 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 | 8 | uri->params.s = p + 1; |
1287 | 8 | uri->params.len = |
1288 | 8 | uri->user.s + uri->user.len - uri->params.s; |
1289 | 8 | uri->user.len = p - uri->user.s; |
1290 | 58 | } else { |
1291 | 58 | uri->params.s = 0; |
1292 | 58 | uri->params.len = 0; |
1293 | 58 | } |
1294 | 2.08k | } else { |
1295 | 2.08k | uri->flags &= ~URI_USER_NORMALIZE; |
1296 | 2.08k | } |
1297 | 2.14k | break; |
1298 | 3.16k | case TEL_URI_T: |
1299 | 3.16k | case TELS_URI_T: |
1300 | | /* fix tel uris, move the number in uri and empty the host */ |
1301 | 3.16k | uri->user = uri->host; |
1302 | 3.16k | uri->host = _sr_uri_empty; |
1303 | 3.16k | break; |
1304 | | /* urn: do nothing */ |
1305 | 1.26k | case URN_URI_T: |
1306 | 1.26k | 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.57k | } |
1312 | | |
1313 | | /* common sanity checks */ |
1314 | 6.57k | if(uri->port.len > 5) { |
1315 | | /* port value too large */ |
1316 | 32 | goto error_invalid_port; |
1317 | 32 | } |
1318 | 6.53k | if(uri->host.len > 0 && uri->user.len <= 0 && uri->host.s > buf |
1319 | 6.53k | && (*(uri->host.s - 1) == '@' || *uri->host.s == '@')) { |
1320 | | /* '@' before host, but no user part */ |
1321 | 50 | goto error_bad_uri; |
1322 | 50 | } |
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.48k | return 0; |
1362 | | |
1363 | 893 | error_too_short: |
1364 | 893 | LM_DBG("uri too short: <%.*s> (%d)\n", len, ZSW(buf), len); |
1365 | 893 | goto error_exit; |
1366 | 305 | error_bad_char: |
1367 | 305 | LM_DBG("bad char '%c' in state %d" |
1368 | 305 | " parsed: <%.*s> (%d) / <%.*s> (%d)\n", |
1369 | 305 | *p, state, (int)(p - buf), ZSW(buf), (int)(p - buf), len, ZSW(buf), |
1370 | 0 | len); |
1371 | 305 | goto error_exit; |
1372 | 347 | error_bad_host: |
1373 | 347 | LM_DBG("bad host in uri (error at char %c in" |
1374 | 347 | " state %d) parsed: <%.*s>(%d) /<%.*s> (%d)\n", |
1375 | 347 | *p, state, (int)(p - buf), ZSW(buf), (int)(p - buf), len, ZSW(buf), |
1376 | 0 | len); |
1377 | 347 | goto error_exit; |
1378 | 219 | error_bad_port: |
1379 | 219 | LM_DBG("bad port in uri (error at char %c in" |
1380 | 219 | " state %d) parsed: <%.*s>(%d) /<%.*s> (%d)\n", |
1381 | 219 | *p, state, (int)(p - buf), ZSW(buf), (int)(p - buf), len, ZSW(buf), |
1382 | 0 | len); |
1383 | 219 | 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 | 313 | error_bad_uri: |
1389 | 313 | 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 | 313 | 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 | 117 | error_bug: |
1397 | 234 | LM_CRIT("BUG: bad state %d parsed: <%.*s> (%d) / <%.*s> (%d)\n", state, |
1398 | 234 | (int)(p - buf), ZSW(buf), (int)(p - buf), len, ZSW(buf), len); |
1399 | 2.24k | error_exit: |
1400 | 2.24k | ser_error = E_BAD_URI; |
1401 | 2.24k | uri->type = ERROR_URI_T; |
1402 | 2.24k | STATS_BAD_URI(); |
1403 | 2.24k | return E_BAD_URI; |
1404 | 117 | } |
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 | } |