/src/opensips/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 opensips, a free SIP server. |
5 | | * |
6 | | * opensips 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 | | * opensips 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 | | * History: |
21 | | * -------- |
22 | | * 2003-04-04 convenience inbound-uri parser parse_orig_ruri |
23 | | * introduced (jiri) |
24 | | * 2003-04-11 new parse_uri introduced (better, parses also some parameters, |
25 | | * works in one pass) (andrei) |
26 | | * 2003-04-11 ser_error is now set in parse_uri (andrei) |
27 | | * 2003-04-26 ZSW (jiri) |
28 | | * 2003-07-03 sips:, r2, lr=on support added (andrei) |
29 | | * 2005-02-25 preliminary tel uri support (andrei) |
30 | | * 2005-03-03 more tel uri fixes (andrei) |
31 | | * 2006-11-28 Added statistic support for the number of bad URI's |
32 | | * (Jeffrey Magder - SOMA Networks) |
33 | | * 2011-04-20 added support for URI unknown parameters (osas) |
34 | | */ |
35 | | |
36 | | |
37 | | #include "parse_uri.h" |
38 | | #include <string.h> |
39 | | #include "../dprint.h" |
40 | | #include "../ut.h" /* q_memchr */ |
41 | | #include "../error.h" |
42 | | #include "../errinfo.h" |
43 | | #include "../core_stats.h" |
44 | | #include "../strcommon.h" |
45 | | |
46 | | static const str uri_type_names[7] = { |
47 | | {NULL, 0}, /*This is the error type*/ |
48 | | str_init("sip"), |
49 | | str_init("sips"), |
50 | | str_init("tel"), |
51 | | str_init("tels"), |
52 | | str_init("urn:service"), |
53 | | str_init("urn:nena:service") |
54 | | }; |
55 | | |
56 | | char* uri_type2str(const uri_type type, char *result) |
57 | 0 | { |
58 | 0 | if (type == ERROR_URI_T) |
59 | 0 | return NULL; |
60 | | |
61 | 0 | memcpy(result, uri_type_names[type].s, uri_type_names[type].len); |
62 | 0 | return result + uri_type_names[type].len; |
63 | 0 | } |
64 | | |
65 | | int uri_typestrlen(const uri_type type) |
66 | 0 | { |
67 | 0 | return uri_type_names[type].len; |
68 | 0 | } |
69 | | |
70 | | uri_type str2uri_type(char * buf) |
71 | 0 | { |
72 | 0 | int scheme = 0; |
73 | 0 | uri_type type = ERROR_URI_T; |
74 | 0 | scheme=buf[0]+(buf[1]<<8)+(buf[2]<<16)+(buf[3]<<24); |
75 | 0 | scheme|=0x20202020; |
76 | 0 | if (scheme==SIP_SCH){ |
77 | 0 | type=SIP_URI_T; |
78 | 0 | }else if(scheme==SIPS_SCH){ |
79 | 0 | if(buf[4]==':') |
80 | 0 | type=SIPS_URI_T; |
81 | 0 | else type = ERROR_URI_T; |
82 | 0 | }else if (scheme==TEL_SCH){ |
83 | 0 | type=TEL_URI_T; |
84 | 0 | }else if (scheme==URN_SERVICE_SCH){ |
85 | 0 | if (memcmp(buf+3,URN_SERVICE_STR,URN_SERVICE_STR_LEN) == 0) { |
86 | 0 | type=URN_SERVICE_URI_T; |
87 | 0 | } |
88 | 0 | else if (memcmp(buf+3,URN_NENA_SERVICE_STR,URN_NENA_SERVICE_STR_LEN) == 0) { |
89 | 0 | type=URN_NENA_SERVICE_URI_T; |
90 | 0 | } |
91 | 0 | } |
92 | 0 | return type; |
93 | 0 | } |
94 | | |
95 | | int parse_uri_headers(str headers, str h_name[], str h_val[], int h_size) |
96 | 0 | { |
97 | 0 | enum states {URI_H_HEADER, URI_H_VALUE}; |
98 | 0 | register enum states state; |
99 | 0 | char* h; /* header start */ |
100 | 0 | char* v; /* header value start */ |
101 | 0 | str* header; /* current header */ |
102 | 0 | str* header_val; /* current header val */ |
103 | 0 | register char* p; |
104 | 0 | char* end; |
105 | 0 | unsigned int i = 0; |
106 | | |
107 | | /* init */ |
108 | 0 | end = headers.s + headers.len; |
109 | 0 | p = h = headers.s; |
110 | 0 | v = NULL; |
111 | 0 | header = &h_name[0]; |
112 | 0 | header_val = &h_val[0]; |
113 | 0 | state = URI_H_HEADER; |
114 | 0 | memset(h_name, 0, h_size * sizeof(str)); |
115 | 0 | memset(h_val, 0, h_size * sizeof(str)); |
116 | |
|
117 | 0 | for(;p<end; p++){ |
118 | 0 | switch((unsigned char)state){ |
119 | 0 | case URI_H_HEADER: |
120 | 0 | switch(*p){ |
121 | 0 | case '=': |
122 | 0 | v = p+1; |
123 | 0 | header->s = h; |
124 | 0 | header->len = p-h; |
125 | 0 | state = URI_H_VALUE; |
126 | 0 | break; |
127 | 0 | case '?': |
128 | 0 | LM_ERR("Header without value\n"); |
129 | 0 | h = p+1; |
130 | 0 | header->s = h; |
131 | 0 | header->len = p-h; |
132 | 0 | header_val->s = NULL; |
133 | 0 | header_val->len = 0; |
134 | | |
135 | | /* advance header and header_val */ |
136 | 0 | i++; |
137 | 0 | if(i<h_size){ |
138 | 0 | header = &h_name[i]; |
139 | 0 | header_val = &h_val[i]; |
140 | 0 | } else { |
141 | 0 | LM_ERR("To many URI headers\n"); |
142 | 0 | return -1; |
143 | 0 | } |
144 | 0 | break; |
145 | 0 | } |
146 | 0 | break; |
147 | 0 | case URI_H_VALUE: |
148 | 0 | switch(*p){ |
149 | 0 | case '=': |
150 | 0 | LM_ERR("Ignoring unexpected '=' inside URI header value\n"); |
151 | 0 | break; |
152 | 0 | case '?': |
153 | 0 | h = p+1; |
154 | 0 | header_val->s = v; |
155 | 0 | header_val->len = p-v; |
156 | 0 | state = URI_H_HEADER; |
157 | | |
158 | | /* advance header and header_val */ |
159 | 0 | i++; |
160 | 0 | if(i<h_size){ |
161 | 0 | header = &h_name[i]; |
162 | 0 | header_val = &h_val[i]; |
163 | 0 | } else { |
164 | 0 | LM_ERR("To many URI headers\n"); |
165 | 0 | return -1; |
166 | 0 | } |
167 | 0 | break; |
168 | 0 | } |
169 | 0 | break; |
170 | 0 | default: |
171 | 0 | LM_ERR("Unexpected state [%d]\n", state); |
172 | 0 | return -1; |
173 | 0 | } |
174 | 0 | } |
175 | | |
176 | 0 | switch(state){ |
177 | 0 | case URI_H_HEADER: |
178 | 0 | LM_ERR("Header without value\n"); |
179 | 0 | header->s = h; |
180 | 0 | header->len = p-h; |
181 | 0 | header_val->s = NULL; |
182 | 0 | header_val->len = 0; |
183 | 0 | break; |
184 | 0 | case URI_H_VALUE: |
185 | 0 | header_val->s = v; |
186 | 0 | header_val->len = p-v; |
187 | 0 | break; |
188 | 0 | } |
189 | | |
190 | | #ifdef EXTRA_DEBUG |
191 | | for(i=0; i<h_size && h_name[i].s; i++) |
192 | | LM_DBG("header=[%p]-><%.*s> val=[%p]-><%.*s>\n", |
193 | | h_name[i].s, h_name[i].len, h_name[i].s, |
194 | | h_val[i].s, h_val[i].len, h_val[i].s); |
195 | | #endif |
196 | | |
197 | 0 | return 0; |
198 | 0 | } |
199 | | |
200 | | int print_uri(struct sip_uri *uri, str *out_buf) |
201 | 0 | { |
202 | 0 | #define append_str_chunk(field) \ |
203 | 0 | do { \ |
204 | 0 | if (bytes + uri->field.len > out_buf->len) { \ |
205 | 0 | LM_ERR("no more space left! printed so far: '%.*s'\n", \ |
206 | 0 | bytes, out_buf->s); \ |
207 | 0 | return -1; \ |
208 | 0 | } \ |
209 | 0 | memcpy(out_buf->s + bytes, uri->field.s, uri->field.len); \ |
210 | 0 | bytes += uri->field.len; \ |
211 | 0 | } while (0) |
212 | |
|
213 | 0 | #define append_char(ch) \ |
214 | 0 | do { \ |
215 | 0 | if (bytes + 1 > out_buf->len) { \ |
216 | 0 | LM_ERR("no more space left! printed so far: '%.*s'\n", \ |
217 | 0 | bytes, out_buf->s); \ |
218 | 0 | return -1; \ |
219 | 0 | } \ |
220 | 0 | out_buf->s[bytes++] = ch; \ |
221 | 0 | } while (0) |
222 | |
|
223 | 0 | #define VAL(p) p##_val |
224 | |
|
225 | 0 | #define append_param(p) \ |
226 | 0 | do { \ |
227 | 0 | if (uri->p.s) { \ |
228 | 0 | append_char(';'); \ |
229 | 0 | append_str_chunk(p); \ |
230 | 0 | } \ |
231 | 0 | } while (0) |
232 | |
|
233 | 0 | #define append_uk_param(idx) \ |
234 | 0 | do { \ |
235 | 0 | if (uri->u_name[idx].s) { \ |
236 | 0 | append_char(';'); \ |
237 | 0 | if (bytes + uri->u_name[idx].len > out_buf->len) { \ |
238 | 0 | LM_ERR("no more space left! printed so far: '%.*s'\n", \ |
239 | 0 | bytes, out_buf->s); \ |
240 | 0 | return -1; \ |
241 | 0 | } \ |
242 | 0 | memcpy(out_buf->s + bytes, uri->u_name[idx].s, uri->u_name[idx].len); \ |
243 | 0 | bytes += uri->u_name[idx].len; \ |
244 | 0 | if (uri->u_val[idx].s) { \ |
245 | 0 | append_char('='); \ |
246 | 0 | if (bytes + uri->u_val[idx].len > out_buf->len) { \ |
247 | 0 | LM_ERR("no more space left! printed so far: '%.*s'\n", \ |
248 | 0 | bytes, out_buf->s); \ |
249 | 0 | return -1; \ |
250 | 0 | } \ |
251 | 0 | memcpy(out_buf->s + bytes, uri->u_val[idx].s, uri->u_val[idx].len); \ |
252 | 0 | bytes += uri->u_val[idx].len; \ |
253 | 0 | } \ |
254 | 0 | } \ |
255 | 0 | } while (0) |
256 | |
|
257 | 0 | int bytes = 0; |
258 | 0 | int i; |
259 | |
|
260 | 0 | memcpy(out_buf->s, uri_type_names[uri->type].s, uri_type_names[uri->type].len); |
261 | 0 | bytes += uri_type_names[uri->type].len; |
262 | 0 | append_char(':'); |
263 | 0 | append_str_chunk(user); |
264 | 0 | if (uri->passwd.s) { |
265 | 0 | append_char(':'); |
266 | 0 | append_str_chunk(passwd); |
267 | 0 | } |
268 | 0 | if (uri->host.s) { |
269 | 0 | append_char('@'); |
270 | 0 | append_str_chunk(host); |
271 | 0 | } |
272 | 0 | if (uri->port.s) { |
273 | 0 | append_char(':'); |
274 | 0 | append_str_chunk(port); |
275 | 0 | } |
276 | | |
277 | 0 | append_param(transport); |
278 | 0 | append_param(ttl); |
279 | 0 | append_param(user_param); |
280 | 0 | append_param(maddr); |
281 | 0 | append_param(method); |
282 | 0 | append_param(lr); |
283 | 0 | append_param(r2); |
284 | 0 | append_param(gr); |
285 | 0 | append_param(pn_provider); |
286 | 0 | append_param(pn_prid); |
287 | 0 | append_param(pn_param); |
288 | 0 | append_param(pn_purr); |
289 | | |
290 | 0 | for (i = 0; i < uri->u_params_no; i++) |
291 | 0 | append_uk_param(i); |
292 | | |
293 | 0 | out_buf->len = bytes; |
294 | |
|
295 | 0 | return 0; |
296 | 0 | #undef append_str_chunk |
297 | 0 | #undef append_char |
298 | 0 | #undef VAL |
299 | 0 | #undef append_param |
300 | 0 | #undef append_uk_param |
301 | 0 | } |
302 | | |
303 | | /* buf= pointer to beginning of uri (sip:x@foo.bar:5060;a=b?h=i) |
304 | | * len= len of uri |
305 | | * returns: fills uri & returns <0 on error or 0 if ok |
306 | | */ |
307 | | int parse_uri(char* buf, int len, struct sip_uri* uri) |
308 | 139k | { |
309 | 139k | enum states { URI_INIT, URI_USER, URI_PASSWORD, URI_PASSWORD_ALPHA, |
310 | 139k | URI_HOST, URI_HOST_P, |
311 | 139k | URI_HOST6_P, URI_HOST6_END, URI_PORT, |
312 | 139k | URI_PARAM, URI_PARAM_P, URI_PARAM_VAL_P, |
313 | 139k | URI_VAL_P, URI_HEADERS, |
314 | | /* param states */ |
315 | | /* transport */ |
316 | 139k | PT_T, PT_R, PT_A, PT_N, PT_S, PT_P, PT_O, PT_R2, PT_T2, |
317 | 139k | PT_eq, |
318 | | /* ttl */ |
319 | 139k | PTTL_T2, PTTL_L, PTTL_eq, |
320 | | /* user */ |
321 | 139k | PU_U, PU_S, PU_E, PU_R, PU_eq, |
322 | | /* method */ |
323 | 139k | PM_M, PM_E, PM_T, PM_H, PM_O, PM_D, PM_eq, |
324 | | /* maddr */ |
325 | 139k | PMA_A, PMA_D, PMA_D2, PMA_R, PMA_eq, |
326 | | /* lr */ |
327 | 139k | PLR_L, PLR_R_FIN, PLR_eq, |
328 | | /* gr */ |
329 | 139k | PG_G, PG_G_FIN, PG_eq, |
330 | | /* r2 */ |
331 | 139k | PR2_R, PR2_2_FIN, PR2_eq, |
332 | | /* transport values */ |
333 | | /* udp */ |
334 | 139k | VU_U, VU_D, VU_P_FIN, |
335 | | /* tcp */ |
336 | 139k | VT_T, VT_C, VT_P_FIN, |
337 | | /* tls */ |
338 | 139k | VTLS_L, VTLS_S_FIN, |
339 | | /* sctp */ |
340 | 139k | VS_S, VS_C, VS_T, VS_P_FIN, |
341 | | /* ws */ |
342 | 139k | VW_W, VW_S, VW_S_FIN, VWS_S_FIN, |
343 | | |
344 | | /* pn-{provider, prid, param, purr} (RFC 8599 - SIP PN) */ |
345 | 139k | PN_P, PN_N, PN_dash, PN_P2, PN_PR, |
346 | 139k | PN1_O, PN1_V, PN1_I, PN1_D, PN1_E, PN1_FIN, PN1_eq, |
347 | 139k | PN2_I, PN2_D, PN2_eq, |
348 | 139k | PN3_A, PN3_R, PN3_A2, PN3_M, PN3_eq, |
349 | 139k | PN4_U, PN4_R, PN4_R2, PN4_eq, |
350 | | |
351 | 139k | }; |
352 | 139k | register enum states state; |
353 | 139k | char* s; |
354 | 139k | char* b; /* param start */ |
355 | 139k | char *v; /* value start */ |
356 | 139k | str* param; /* current param */ |
357 | 139k | str* param_val; /* current param val */ |
358 | 139k | str user; |
359 | 139k | str password; |
360 | 139k | unsigned int port_no; |
361 | 139k | register char* p; |
362 | 139k | char* end; |
363 | 139k | char* pass; |
364 | 139k | int found_user; |
365 | 139k | int error_headers; |
366 | 139k | unsigned int scheme; |
367 | 139k | uri_type backup; |
368 | | #ifdef EXTRA_DEBUG |
369 | | int i; |
370 | | #endif |
371 | | |
372 | 139k | #define case_port( ch, var, ovf_check1, ovf_check2) \ |
373 | 139k | case ch: \ |
374 | 56.5k | if (ovf_check1) \ |
375 | 56.5k | (var)=(var)*10+(ch-'0'); \ |
376 | 56.5k | if (ovf_check2 && (var) > USHRT_MAX) \ |
377 | 56.5k | goto error_bad_port; \ |
378 | 56.5k | break |
379 | | |
380 | 139k | #define still_at_user \ |
381 | 139k | if (found_user==0){ \ |
382 | 21.0k | user.s=uri->host.s; \ |
383 | 21.0k | if (pass){\ |
384 | 8.56k | user.len=pass-user.s; \ |
385 | 8.56k | password.s=pass+1; \ |
386 | 8.56k | password.len=p-password.s; \ |
387 | 12.4k | }else{ \ |
388 | 12.4k | user.len=p-user.s; \ |
389 | 12.4k | }\ |
390 | | /* save the uri type/scheme */ \ |
391 | 21.0k | backup=uri->type; \ |
392 | | /* everything else is 0 */ \ |
393 | 21.0k | memset(uri, 0, sizeof(struct sip_uri)); \ |
394 | | /* restore the scheme, copy user & pass */ \ |
395 | 21.0k | uri->type=backup; \ |
396 | 21.0k | uri->user=user; \ |
397 | 21.0k | if (pass) uri->passwd=password; \ |
398 | 21.0k | s=p+1; \ |
399 | 21.0k | found_user=1;\ |
400 | 21.0k | error_headers=0; \ |
401 | 21.0k | state=URI_HOST; \ |
402 | 21.0k | }else goto error_bad_char |
403 | | |
404 | 139k | #define check_host_end \ |
405 | 139k | case ':': \ |
406 | | /* found the host */ \ |
407 | 3.03k | uri->host.s=s; \ |
408 | 3.03k | uri->host.len=p-s; \ |
409 | 3.03k | state=URI_PORT; \ |
410 | 3.03k | s=p+1; \ |
411 | 3.03k | break; \ |
412 | 11.3k | case ';': \ |
413 | 11.3k | uri->host.s=s; \ |
414 | 11.3k | uri->host.len=p-s; \ |
415 | 11.3k | state=URI_PARAM; \ |
416 | 11.3k | s=p+1; \ |
417 | 11.3k | break; \ |
418 | 11.3k | case '?': \ |
419 | 168 | uri->host.s=s; \ |
420 | 168 | uri->host.len=p-s; \ |
421 | 168 | state=URI_HEADERS; \ |
422 | 168 | s=p+1; \ |
423 | 168 | break; \ |
424 | 168 | case '&': \ |
425 | 545 | case '@': \ |
426 | 545 | goto error_bad_char |
427 | | |
428 | | |
429 | 139k | #define param_set(t_start, v_start) \ |
430 | 139k | param->s=(t_start);\ |
431 | 76.8k | param->len=(p-(t_start));\ |
432 | 76.8k | param_val->s=(v_start); \ |
433 | 76.8k | param_val->len=(p-(v_start)) |
434 | | |
435 | 139k | #define u_param_set(t_start, v_start) \ |
436 | 419k | if (uri->u_params_no < URI_MAX_U_PARAMS){ \ |
437 | 134k | if((v_start)>(t_start)){ \ |
438 | 6.30k | uri->u_name[uri->u_params_no].s=(t_start); \ |
439 | 6.30k | uri->u_name[uri->u_params_no].len=((v_start)-(t_start)-1); \ |
440 | 6.30k | if(p>(v_start)) { \ |
441 | 4.27k | uri->u_val[uri->u_params_no].s=(v_start); \ |
442 | 4.27k | uri->u_val[uri->u_params_no].len=(p-(v_start)); \ |
443 | 4.27k | } \ |
444 | 128k | } else { \ |
445 | 128k | uri->u_name[uri->u_params_no].s=(t_start); \ |
446 | 128k | uri->u_name[uri->u_params_no].len=(p-(t_start)); \ |
447 | 128k | } \ |
448 | 134k | uri->u_params_no++; \ |
449 | 284k | } else { \ |
450 | 284k | LM_ERR("unknown URI param list excedeed\n"); \ |
451 | 284k | } |
452 | | |
453 | 139k | #define semicolon_case \ |
454 | 546k | case';': \ |
455 | 546k | if (pass){ \ |
456 | 10.8k | found_user=1;/* no user, pass cannot contain ';'*/ \ |
457 | 10.8k | pass=0; \ |
458 | 10.8k | } \ |
459 | 546k | state=URI_PARAM /* new param */ |
460 | | |
461 | 139k | #define question_case \ |
462 | 139k | case '?': \ |
463 | 18.6k | uri->params.s=s; \ |
464 | 18.6k | uri->params.len=p-s; \ |
465 | 18.6k | state=URI_HEADERS; \ |
466 | 18.6k | s=p+1; \ |
467 | 18.6k | if (pass){ \ |
468 | 4.08k | found_user=1;/* no user, pass cannot contain '?'*/ \ |
469 | 4.08k | pass=0; \ |
470 | 4.08k | } |
471 | | |
472 | 139k | #define colon_case \ |
473 | 169k | case ':': \ |
474 | 169k | if (found_user==0){ \ |
475 | | /*might be pass but only if user not found yet*/ \ |
476 | 18.6k | if (pass){ \ |
477 | 1.25k | found_user=1; /* no user */ \ |
478 | 1.25k | pass=0; \ |
479 | 17.3k | }else{ \ |
480 | 17.3k | pass=p; \ |
481 | 17.3k | } \ |
482 | 18.6k | } \ |
483 | 169k | state=URI_PARAM_P /* generic param */ |
484 | | |
485 | 139k | #define param_common_cases \ |
486 | 139k | case '@': \ |
487 | | /* ughhh, this is still the user */ \ |
488 | 5.01k | still_at_user; \ |
489 | 2.30k | break; \ |
490 | 67.2k | semicolon_case; \ |
491 | 67.2k | break; \ |
492 | 67.2k | question_case; \ |
493 | 3.33k | break; \ |
494 | 24.4k | colon_case; \ |
495 | 24.4k | break |
496 | | |
497 | 139k | #define u_param_common_cases \ |
498 | 139k | case '@': \ |
499 | | /* ughhh, this is still the user */ \ |
500 | 21.6k | still_at_user; \ |
501 | 12.1k | break; \ |
502 | 402k | semicolon_case; \ |
503 | 402k | u_param_set(b, v); \ |
504 | 402k | break; \ |
505 | 402k | question_case; \ |
506 | 12.1k | u_param_set(b, v); \ |
507 | 12.1k | break; \ |
508 | 121k | colon_case; \ |
509 | 121k | break |
510 | | |
511 | 139k | #define value_common_cases \ |
512 | 139k | case '@': \ |
513 | | /* ughhh, this is still the user */ \ |
514 | 3.11k | still_at_user; \ |
515 | 1.71k | break; \ |
516 | 66.6k | semicolon_case; \ |
517 | 66.6k | param_set(b, v); \ |
518 | 66.6k | break; \ |
519 | 66.6k | question_case; \ |
520 | 1.93k | param_set(b, v); \ |
521 | 1.93k | break; \ |
522 | 16.6k | colon_case; \ |
523 | 16.6k | state=URI_VAL_P; \ |
524 | 16.6k | break |
525 | | |
526 | 139k | #define param_switch(old_state, c1, c2, new_state) \ |
527 | 1.34M | case old_state: \ |
528 | 1.34M | switch(*p){ \ |
529 | 666k | case c1: \ |
530 | 1.13M | case c2: \ |
531 | 1.13M | state=(new_state); \ |
532 | 1.13M | break; \ |
533 | 666k | u_param_common_cases; \ |
534 | 98.6k | default: \ |
535 | 98.6k | state=URI_PARAM_P; \ |
536 | 1.34M | } \ |
537 | 1.34M | break |
538 | 139k | #define param_switch1(old_state, c1, new_state) \ |
539 | 222k | case old_state: \ |
540 | 222k | switch(*p){ \ |
541 | 177k | case c1: \ |
542 | 177k | state=(new_state); \ |
543 | 177k | break; \ |
544 | 830 | param_common_cases; \ |
545 | 30.1k | default: \ |
546 | 30.1k | state=URI_PARAM_P; \ |
547 | 222k | } \ |
548 | 222k | break |
549 | 139k | #define param_xswitch1(old_state, c1, new_state) \ |
550 | 139k | case old_state: \ |
551 | 6.99k | switch(*p){ \ |
552 | 6.46k | case c1: \ |
553 | 6.46k | state=(new_state); \ |
554 | 6.46k | break; \ |
555 | 532 | default: \ |
556 | 532 | goto error_bad_char; \ |
557 | 6.99k | } \ |
558 | 6.99k | break |
559 | 139k | #define param_switch_big(old_state, c1, c2, d1, d2, new_state_c, new_state_d) \ |
560 | 295k | case old_state : \ |
561 | 295k | switch(*p){ \ |
562 | 144k | case c1: \ |
563 | 203k | case c2: \ |
564 | 203k | state=(new_state_c); \ |
565 | 203k | break; \ |
566 | 144k | case d1: \ |
567 | 38.7k | case d2: \ |
568 | 38.7k | state=(new_state_d); \ |
569 | 38.7k | break; \ |
570 | 32.1k | u_param_common_cases; \ |
571 | 28.6k | default: \ |
572 | 28.6k | state=URI_PARAM_P; \ |
573 | 295k | } \ |
574 | 295k | break |
575 | 139k | #define param_switch_bigger(old_state, c1, c2, d1, d2, e1, e2, new_state_c, new_state_d, new_state_e) \ |
576 | 139k | case old_state : \ |
577 | 100k | switch(*p){ \ |
578 | 51.6k | case c1: \ |
579 | 74.3k | case c2: \ |
580 | 74.3k | state=(new_state_c); \ |
581 | 74.3k | break; \ |
582 | 51.6k | case d1: \ |
583 | 10.3k | case d2: \ |
584 | 10.3k | state=(new_state_d); \ |
585 | 10.3k | break; \ |
586 | 6.06k | case e1: \ |
587 | 10.0k | case e2: \ |
588 | 10.0k | state=(new_state_e); \ |
589 | 10.0k | break; \ |
590 | 6.06k | u_param_common_cases; \ |
591 | 2.36k | default: \ |
592 | 2.36k | state=URI_PARAM_P; \ |
593 | 100k | } \ |
594 | 100k | break |
595 | 139k | #define value_switch(old_state, c1, c2, new_state) \ |
596 | 139k | case old_state: \ |
597 | 71.2k | switch(*p){ \ |
598 | 14.6k | case c1: \ |
599 | 38.9k | case c2: \ |
600 | 38.9k | state=(new_state); \ |
601 | 38.9k | break; \ |
602 | 14.6k | value_common_cases; \ |
603 | 12.7k | default: \ |
604 | 12.7k | state=URI_VAL_P; \ |
605 | 71.2k | } \ |
606 | 71.2k | break |
607 | 139k | #define value_switch_big(old_state, c1, c2, d1, d2, new_state_c, new_state_d) \ |
608 | 139k | case old_state: \ |
609 | 18.1k | switch(*p){ \ |
610 | 5.15k | case c1: \ |
611 | 7.41k | case c2: \ |
612 | 7.41k | state=(new_state_c); \ |
613 | 7.41k | break; \ |
614 | 5.15k | case d1: \ |
615 | 5.81k | case d2: \ |
616 | 5.81k | state=(new_state_d); \ |
617 | 5.81k | break; \ |
618 | 4.39k | value_common_cases; \ |
619 | 717 | default: \ |
620 | 717 | state=URI_VAL_P; \ |
621 | 18.1k | } \ |
622 | 18.1k | break |
623 | | |
624 | 139k | #define transport_fin(c_state, proto_no) \ |
625 | 139k | case c_state: \ |
626 | 15.3k | switch(*p){ \ |
627 | 588 | case '@': \ |
628 | 588 | still_at_user; \ |
629 | 588 | break; \ |
630 | 6.45k | semicolon_case; \ |
631 | 6.45k | param_set(b, v); \ |
632 | 6.45k | uri->proto=(proto_no); \ |
633 | 6.45k | break; \ |
634 | 665 | question_case; \ |
635 | 665 | param_set(b, v); \ |
636 | 665 | uri->proto=(proto_no); \ |
637 | 665 | break; \ |
638 | 3.31k | colon_case; \ |
639 | 7.59k | default: \ |
640 | 7.59k | state=URI_VAL_P; \ |
641 | 7.59k | break; \ |
642 | 15.3k | } \ |
643 | 15.3k | break |
644 | | |
645 | | |
646 | | |
647 | | /* init */ |
648 | 139k | end=buf+len; |
649 | 139k | p=buf+4; |
650 | 139k | found_user=0; |
651 | 139k | error_headers=0; |
652 | 139k | b=v=0; |
653 | 139k | param=param_val=0; |
654 | 139k | pass=0; |
655 | 139k | password.s = 0; |
656 | 139k | password.len = 0; |
657 | 139k | port_no=0; |
658 | 139k | state=URI_INIT; |
659 | 139k | memset(uri, 0, sizeof(struct sip_uri)); /* zero it all, just to be sure*/ |
660 | | /*look for sip:, sips: or tel:*/ |
661 | 139k | if (len<5) goto error_too_short; |
662 | 63.3k | scheme=(unsigned)(unsigned char)buf[0] |
663 | 63.3k | + (((unsigned)(unsigned char)buf[1])<<8) |
664 | 63.3k | + (((unsigned)(unsigned char)buf[2])<<16) |
665 | 63.3k | + (((unsigned)(unsigned char)buf[3])<<24); |
666 | 63.3k | scheme|=0x20202020; |
667 | 63.3k | if (scheme==SIP_SCH){ |
668 | 51.7k | uri->type=SIP_URI_T; |
669 | 51.7k | }else if(scheme==SIPS_SCH){ |
670 | 371 | if(buf[4]==':'){ p++; uri->type=SIPS_URI_T;} |
671 | 188 | else goto error_bad_uri; |
672 | 11.2k | }else if (scheme==TEL_SCH){ |
673 | 5.66k | uri->type=TEL_URI_T; |
674 | 5.66k | }else if (scheme==URN_SERVICE_SCH){ |
675 | 1.71k | if ((end-(buf+3)) >= URN_SERVICE_STR_LEN |
676 | 1.71k | && memcmp(buf+3,URN_SERVICE_STR,URN_SERVICE_STR_LEN) == 0) { |
677 | 46 | p+= URN_SERVICE_STR_LEN-1; |
678 | 46 | uri->type=URN_SERVICE_URI_T; |
679 | 46 | } |
680 | 1.67k | else if ((end-(buf+3)) >= URN_NENA_SERVICE_STR_LEN |
681 | 1.67k | && memcmp(buf+3,URN_NENA_SERVICE_STR,URN_NENA_SERVICE_STR_LEN) == 0) { |
682 | 60 | p+= URN_NENA_SERVICE_STR_LEN-1; |
683 | 60 | uri->type=URN_NENA_SERVICE_URI_T; |
684 | 1.61k | }else goto error_bad_uri; |
685 | 3.90k | }else goto error_bad_uri; |
686 | | |
687 | 57.6k | s=p; |
688 | 6.49M | for(;p<end; p++){ |
689 | 6.46M | switch((unsigned char)state){ |
690 | 57.5k | case URI_INIT: |
691 | 57.5k | switch(*p){ |
692 | 994 | case '[': |
693 | | /* uri = [ipv6address]... */ |
694 | 994 | state=URI_HOST6_P; |
695 | 994 | s=p; |
696 | 994 | break; |
697 | 39 | case ']': |
698 | | /* invalid, no uri can start with ']' */ |
699 | 92 | case ':': |
700 | | /* the same as above for ':' */ |
701 | 92 | goto error_bad_char; |
702 | 39 | case '@': /* error no user part */ |
703 | 39 | goto error_bad_char; |
704 | 56.4k | default: |
705 | 56.4k | state=URI_USER; |
706 | 57.5k | } |
707 | 57.4k | break; |
708 | 114k | case URI_USER: |
709 | 114k | switch(*p){ |
710 | 3.21k | case '@': |
711 | | /* found the user*/ |
712 | 3.21k | uri->user.s=s; |
713 | 3.21k | uri->user.len=p-s; |
714 | 3.21k | state=URI_HOST; |
715 | 3.21k | found_user=1; |
716 | 3.21k | s=p+1; /* skip '@' */ |
717 | 3.21k | break; |
718 | 10.9k | case ':': |
719 | | /* found the user, or the host? */ |
720 | 10.9k | uri->user.s=s; |
721 | 10.9k | uri->user.len=p-s; |
722 | 10.9k | state=URI_PASSWORD; |
723 | 10.9k | s=p+1; /* skip ':' */ |
724 | 10.9k | break; |
725 | 40.6k | case ';': |
726 | | /* this could be still the user or |
727 | | * params?*/ |
728 | 40.6k | uri->host.s=s; |
729 | 40.6k | uri->host.len=p-s; |
730 | 40.6k | state=URI_PARAM; |
731 | 40.6k | s=p+1; |
732 | 40.6k | break; |
733 | 1.38k | case '?': /* still user or headers? */ |
734 | 1.38k | uri->host.s=s; |
735 | 1.38k | uri->host.len=p-s; |
736 | 1.38k | state=URI_HEADERS; |
737 | 1.38k | s=p+1; |
738 | 1.38k | break; |
739 | | /* almost anything permitted in the user part */ |
740 | 57 | case '[': |
741 | 115 | case ']': /* the user part cannot contain "[]" */ |
742 | 115 | goto error_bad_char; |
743 | 114k | } |
744 | 113k | break; |
745 | 113k | case URI_PASSWORD: /* this can also be the port (missing user)*/ |
746 | 53.8k | switch(*p){ |
747 | 453 | case '@': |
748 | | /* found the password*/ |
749 | 453 | uri->passwd.s=s; |
750 | 453 | uri->passwd.len=p-s; |
751 | 453 | port_no=0; |
752 | 453 | state=URI_HOST; |
753 | 453 | found_user=1; |
754 | 453 | s=p+1; /* skip '@' */ |
755 | 453 | break; |
756 | 5.46k | case ';': |
757 | | /* upps this is the port */ |
758 | 5.46k | uri->port.s=s; |
759 | 5.46k | uri->port.len=p-s; |
760 | 5.46k | uri->port_no=port_no; |
761 | | /* user contains in fact the host */ |
762 | 5.46k | uri->host.s=uri->user.s; |
763 | 5.46k | uri->host.len=uri->user.len; |
764 | 5.46k | uri->user.s=0; |
765 | 5.46k | uri->user.len=0; |
766 | 5.46k | state=URI_PARAM; |
767 | 5.46k | found_user=1; /* there is no user part */ |
768 | 5.46k | s=p+1; |
769 | 5.46k | break; |
770 | 136 | case '?': |
771 | | /* upps this is the port */ |
772 | 136 | uri->port.s=s; |
773 | 136 | uri->port.len=p-s; |
774 | 136 | uri->port_no=port_no; |
775 | | /* user contains in fact the host */ |
776 | 136 | uri->host.s=uri->user.s; |
777 | 136 | uri->host.len=uri->user.len; |
778 | 136 | uri->user.s=0; |
779 | 136 | uri->user.len=0; |
780 | 136 | state=URI_HEADERS; |
781 | 136 | found_user=1; /* there is no user part */ |
782 | 136 | s=p+1; |
783 | 136 | break; |
784 | 5.35k | case_port('0', port_no, port_no < INT_MAX / 10, 0); |
785 | 5.45k | case_port('1', port_no, port_no < INT_MAX / 10, 0); |
786 | 5.68k | case_port('2', port_no, port_no < INT_MAX / 10, 0); |
787 | 5.68k | case_port('3', port_no, port_no < INT_MAX / 10, 0); |
788 | 5.91k | case_port('4', port_no, port_no < INT_MAX / 10, 0); |
789 | 5.91k | case_port('5', port_no, port_no < INT_MAX / 10, 0); |
790 | 3.69k | case_port('6', port_no, port_no < INT_MAX / 10, 0); |
791 | 5.16k | case_port('7', port_no, port_no < INT_MAX / 10, 0); |
792 | 5.16k | case_port('8', port_no, port_no < INT_MAX / 10, 0); |
793 | 5.03k | case_port('9', port_no, port_no < INT_MAX / 10, 0); |
794 | 3.60k | case '[': |
795 | 134 | case ']': |
796 | 233 | case ':': |
797 | 233 | goto error_bad_char; |
798 | 1.36k | default: |
799 | | /* it can't be the port, non number found */ |
800 | 1.36k | port_no=0; |
801 | 1.36k | state=URI_PASSWORD_ALPHA; |
802 | 53.8k | } |
803 | 53.6k | break; |
804 | 53.6k | case URI_PASSWORD_ALPHA: |
805 | 2.41k | switch(*p){ |
806 | 103 | case '@': |
807 | | /* found the password*/ |
808 | 103 | uri->passwd.s=s; |
809 | 103 | uri->passwd.len=p-s; |
810 | 103 | state=URI_HOST; |
811 | 103 | found_user=1; |
812 | 103 | s=p+1; /* skip '@' */ |
813 | 103 | break; |
814 | 57 | case ';': /* contains non-numbers => cannot be port no*/ |
815 | 142 | case '?': |
816 | 142 | goto error_bad_port; |
817 | 67 | case '[': |
818 | 106 | case ']': |
819 | 159 | case ':': |
820 | 159 | goto error_bad_char; |
821 | 2.41k | } |
822 | 2.11k | break; |
823 | 17.1k | case URI_HOST: |
824 | 17.1k | switch(*p){ |
825 | 131 | case '[': |
826 | 131 | state=URI_HOST6_P; |
827 | 131 | break; |
828 | 699 | case ':': |
829 | 1.38k | case ';': |
830 | 1.71k | case '?': /* null host name ->invalid */ |
831 | 1.82k | case '&': |
832 | 2.02k | case '@': /*chars not allowed in hosts names */ |
833 | 2.02k | goto error_bad_host; |
834 | 14.9k | default: |
835 | 14.9k | state=URI_HOST_P; |
836 | 17.1k | } |
837 | 15.0k | break; |
838 | 37.7k | case URI_HOST_P: |
839 | 37.7k | switch(*p){ |
840 | 37.7k | check_host_end; |
841 | 37.7k | } |
842 | 37.2k | break; |
843 | 37.2k | case URI_HOST6_END: |
844 | 750 | switch(*p){ |
845 | 511 | check_host_end; |
846 | 53 | default: /*no chars allowed after [ipv6] */ |
847 | 53 | goto error_bad_host; |
848 | 750 | } |
849 | 637 | break; |
850 | 1.86k | case URI_HOST6_P: |
851 | 1.86k | switch(*p){ |
852 | 772 | case ']': |
853 | 772 | state=URI_HOST6_END; |
854 | 772 | break; |
855 | 39 | case '[': |
856 | 78 | case '&': |
857 | 117 | case '@': |
858 | 170 | case ';': |
859 | 209 | case '?': |
860 | 209 | goto error_bad_host; |
861 | 1.86k | } |
862 | 1.65k | break; |
863 | 12.1k | case URI_PORT: |
864 | 12.1k | switch(*p){ |
865 | 351 | case ';': |
866 | 351 | uri->port.s=s; |
867 | 351 | uri->port.len=p-s; |
868 | 351 | uri->port_no=port_no; |
869 | 351 | state=URI_PARAM; |
870 | 351 | s=p+1; |
871 | 351 | break; |
872 | 45 | case '?': |
873 | 45 | uri->port.s=s; |
874 | 45 | uri->port.len=p-s; |
875 | 45 | uri->port_no=port_no; |
876 | 45 | state=URI_HEADERS; |
877 | 45 | s=p+1; |
878 | 45 | break; |
879 | 1.28k | case_port('0', port_no, 1, 1); |
880 | 1.14k | case_port('1', port_no, 1, 1); |
881 | 1.16k | case_port('2', port_no, 1, 1); |
882 | 1.08k | case_port('3', port_no, 1, 1); |
883 | 954 | case_port('4', port_no, 1, 1); |
884 | 1.40k | case_port('5', port_no, 1, 1); |
885 | 1.57k | case_port('6', port_no, 1, 1); |
886 | 1.47k | case_port('7', port_no, 1, 1); |
887 | 797 | case_port('8', port_no, 1, 1); |
888 | 706 | case_port('9', port_no, 1, 1); |
889 | 618 | case '&': |
890 | 18 | case '@': |
891 | 64 | case ':': |
892 | 1.35k | default: |
893 | 1.35k | goto error_bad_port; |
894 | 12.1k | } |
895 | 9.85k | break; |
896 | 602k | case URI_PARAM: /* beginning of a new param */ |
897 | 602k | switch(*p){ |
898 | 3.14k | param_common_cases; |
899 | | /* recognized params */ |
900 | 128k | case 't': |
901 | 155k | case 'T': |
902 | 155k | b=p; |
903 | 155k | state=PT_T; |
904 | 155k | break; |
905 | 7.53k | case 'u': |
906 | 25.4k | case 'U': |
907 | 25.4k | b=p; |
908 | 25.4k | state=PU_U; |
909 | 25.4k | break; |
910 | 37.4k | case 'm': |
911 | 65.9k | case 'M': |
912 | 65.9k | b=p; |
913 | 65.9k | state=PM_M; |
914 | 65.9k | break; |
915 | 18.4k | case 'l': |
916 | 22.6k | case 'L': |
917 | 22.6k | b=p; |
918 | 22.6k | state=PLR_L; |
919 | 22.6k | break; |
920 | 7.96k | case 'g': |
921 | 12.7k | case 'G': |
922 | 12.7k | b=p; |
923 | 12.7k | state=PG_G; |
924 | 12.7k | break; |
925 | 9.16k | case 'r': |
926 | 16.8k | case 'R': |
927 | 16.8k | b=p; |
928 | 16.8k | state=PR2_R; |
929 | 16.8k | break; |
930 | 132k | case 'p': |
931 | 141k | case 'P': |
932 | 141k | b=p; |
933 | 141k | state=PN_P; |
934 | 141k | break; |
935 | 104k | default: |
936 | 104k | b=p; |
937 | 104k | state=URI_PARAM_P; |
938 | 602k | } |
939 | 600k | break; |
940 | 2.67M | case URI_PARAM_P: /* ignore current param */ |
941 | | /* supported params: |
942 | | * maddr, transport, ttl, lr, user, method, r2 */ |
943 | 2.67M | switch(*p){ |
944 | 16.5k | u_param_common_cases; |
945 | 78.6k | case '=': |
946 | 78.6k | v=p + 1; |
947 | 78.6k | state=URI_PARAM_VAL_P; |
948 | 78.6k | break; |
949 | 2.67M | }; |
950 | 2.67M | break; |
951 | 379k | case URI_PARAM_VAL_P: /* value of the ignored current param */ |
952 | 379k | switch(*p){ |
953 | 379k | u_param_common_cases; |
954 | 379k | }; |
955 | 379k | break; |
956 | | /* ugly but fast param names parsing */ |
957 | | /*transport */ |
958 | 154k | param_switch_big(PT_T, 'r', 'R', 't', 'T', PT_R, PTTL_T2); |
959 | 154k | param_switch(PT_R, 'a', 'A', PT_A); |
960 | 117k | param_switch(PT_A, 'n', 'N', PT_N); |
961 | 99.6k | param_switch(PT_N, 's', 'S', PT_S); |
962 | 91.4k | param_switch(PT_S, 'p', 'P', PT_P); |
963 | 86.8k | param_switch(PT_P, 'o', 'O', PT_O); |
964 | 80.4k | param_switch(PT_O, 'r', 'R', PT_R2); |
965 | 74.3k | param_switch(PT_R2, 't', 'T', PT_T2); |
966 | 66.0k | param_switch1(PT_T2, '=', PT_eq); |
967 | | /* value parsing */ |
968 | 63.2k | case PT_eq: |
969 | 58.9k | param=&uri->transport; |
970 | 58.9k | param_val=&uri->transport_val; |
971 | 58.9k | uri->proto = PROTO_OTHER; |
972 | 58.9k | switch (*p){ |
973 | 96 | param_common_cases; |
974 | 7.25k | case 'u': |
975 | 15.8k | case 'U': |
976 | 15.8k | v=p; |
977 | 15.8k | state=VU_U; |
978 | 15.8k | break; |
979 | 8.90k | case 't': |
980 | 18.1k | case 'T': |
981 | 18.1k | v=p; |
982 | 18.1k | state=VT_T; |
983 | 18.1k | break; |
984 | 3.19k | case 's': |
985 | 12.1k | case 'S': |
986 | 12.1k | v=p; |
987 | 12.1k | state=VS_S; |
988 | 12.1k | break; |
989 | 4.05k | case 'w': |
990 | 6.78k | case 'W': |
991 | 6.78k | v=p; |
992 | 6.78k | state=VW_W; |
993 | 6.78k | break; |
994 | 2.37k | default: |
995 | 2.37k | v=p; |
996 | 2.37k | state=URI_VAL_P; |
997 | 58.9k | } |
998 | 58.9k | break; |
999 | | /* generic value */ |
1000 | 201k | case URI_VAL_P: |
1001 | 201k | switch(*p){ |
1002 | 201k | value_common_cases; |
1003 | 201k | } |
1004 | 200k | break; |
1005 | | /* udp */ |
1006 | 200k | value_switch(VU_U, 'd', 'D', VU_D); |
1007 | 15.8k | value_switch(VU_D, 'p', 'P', VU_P_FIN); |
1008 | 9.60k | transport_fin(VU_P_FIN, PROTO_UDP); |
1009 | | /* tcp */ |
1010 | 18.1k | value_switch_big(VT_T, 'c', 'C', 'l', 'L', VT_C, VTLS_L); |
1011 | 18.0k | value_switch(VT_C, 'p', 'P', VT_P_FIN); |
1012 | 7.34k | transport_fin(VT_P_FIN, PROTO_TCP); |
1013 | | /* tls */ |
1014 | 5.78k | value_switch(VTLS_L, 's', 'S', VTLS_S_FIN); |
1015 | 5.75k | transport_fin(VTLS_S_FIN, PROTO_TLS); |
1016 | | /* sctp */ |
1017 | 12.0k | value_switch(VS_S, 'c', 'C', VS_C); |
1018 | 12.0k | value_switch(VS_C, 't', 'T', VS_T); |
1019 | 9.49k | value_switch(VS_T, 'p', 'P', VS_P_FIN); |
1020 | 4.16k | transport_fin(VS_P_FIN, PROTO_SCTP); |
1021 | | /* ws */ |
1022 | 6.76k | value_switch(VW_W, 's', 'S', VW_S); |
1023 | 6.72k | case VW_S: |
1024 | 4.87k | if (*p == 's' || *p == 'S') { |
1025 | 2.94k | state=(VWS_S_FIN); |
1026 | 2.94k | break; |
1027 | 2.94k | } |
1028 | | /* if not a 's' transiting to VWS_S_FIN, fallback |
1029 | | * to testing as existing VW_S_FIN (NOTE the missing break) */ |
1030 | 1.92k | state=(VW_S_FIN); |
1031 | 1.92k | transport_fin(VW_S_FIN, PROTO_WS); |
1032 | 2.91k | transport_fin(VWS_S_FIN, PROTO_WSS); |
1033 | | |
1034 | | /* ttl */ |
1035 | 12.1k | param_switch(PTTL_T2, 'l', 'L', PTTL_L); |
1036 | 12.1k | param_switch1(PTTL_L, '=', PTTL_eq); |
1037 | 8.07k | case PTTL_eq: |
1038 | 1.65k | param=&uri->ttl; |
1039 | 1.65k | param_val=&uri->ttl_val; |
1040 | 1.65k | switch(*p){ |
1041 | 82 | param_common_cases; |
1042 | 475 | default: |
1043 | 475 | v=p; |
1044 | 475 | state=URI_VAL_P; |
1045 | 1.65k | } |
1046 | 1.61k | break; |
1047 | | |
1048 | | /* user param */ |
1049 | 25.4k | param_switch(PU_U, 's', 'S', PU_S); |
1050 | 25.3k | param_switch(PU_S, 'e', 'E', PU_E); |
1051 | 16.1k | param_switch(PU_E, 'r', 'R', PU_R); |
1052 | 11.7k | param_switch1(PU_R, '=', PU_eq); |
1053 | 7.53k | case PU_eq: |
1054 | 1.68k | param=&uri->user_param; |
1055 | 1.68k | param_val=&uri->user_param_val; |
1056 | 1.68k | switch(*p){ |
1057 | 82 | param_common_cases; |
1058 | 503 | default: |
1059 | 503 | v=p; |
1060 | 503 | state=URI_VAL_P; |
1061 | 1.68k | } |
1062 | 1.65k | break; |
1063 | | |
1064 | | /* method*/ |
1065 | 65.9k | param_switch_big(PM_M, 'e', 'E', 'a', 'A', PM_E, PMA_A); |
1066 | 65.8k | param_switch(PM_E, 't', 'T', PM_T); |
1067 | 30.0k | param_switch(PM_T, 'h', 'H', PM_H); |
1068 | 17.9k | param_switch(PM_H, 'o', 'O', PM_O); |
1069 | 11.4k | param_switch(PM_O, 'd', 'D', PM_D); |
1070 | 6.99k | param_switch1(PM_D, '=', PM_eq); |
1071 | 4.24k | case PM_eq: |
1072 | 1.89k | param=&uri->method; |
1073 | 1.89k | param_val=&uri->method_val; |
1074 | 1.89k | switch(*p){ |
1075 | 82 | param_common_cases; |
1076 | 698 | default: |
1077 | 698 | v=p; |
1078 | 698 | state=URI_VAL_P; |
1079 | 1.89k | } |
1080 | 1.85k | break; |
1081 | | |
1082 | | /*maddr*/ |
1083 | 15.7k | param_switch(PMA_A, 'd', 'D', PMA_D); |
1084 | 15.6k | param_switch(PMA_D, 'd', 'D', PMA_D2); |
1085 | 10.9k | param_switch(PMA_D2, 'r', 'R', PMA_R); |
1086 | 7.39k | param_switch1(PMA_R, '=', PMA_eq); |
1087 | 4.33k | case PMA_eq: |
1088 | 1.78k | param=&uri->maddr; |
1089 | 1.78k | param_val=&uri->maddr_val; |
1090 | 1.78k | switch(*p){ |
1091 | 86 | param_common_cases; |
1092 | 556 | default: |
1093 | 556 | v=p; |
1094 | 556 | state=URI_VAL_P; |
1095 | 1.78k | } |
1096 | 1.74k | break; |
1097 | | |
1098 | | /* lr */ |
1099 | 22.5k | param_switch(PLR_L, 'r', 'R', PLR_R_FIN); |
1100 | 22.4k | case PLR_R_FIN: |
1101 | 5.83k | switch(*p){ |
1102 | 96 | case '@': |
1103 | 96 | still_at_user; |
1104 | 57 | break; |
1105 | 1.86k | case '=': |
1106 | 1.86k | state=PLR_eq; |
1107 | 1.86k | break; |
1108 | 1.29k | semicolon_case; |
1109 | 1.29k | uri->lr.s=b; |
1110 | 1.29k | uri->lr.len=(p-b); |
1111 | 1.29k | break; |
1112 | 149 | question_case; |
1113 | 149 | uri->lr.s=b; |
1114 | 149 | uri->lr.len=(p-b); |
1115 | 149 | break; |
1116 | 684 | colon_case; |
1117 | 684 | break; |
1118 | 1.75k | default: |
1119 | 1.75k | state=URI_PARAM_P; |
1120 | 5.83k | } |
1121 | 5.79k | break; |
1122 | | /* handle lr=something case */ |
1123 | 5.79k | case PLR_eq: |
1124 | 1.84k | param=&uri->lr; |
1125 | 1.84k | param_val=&uri->lr_val; |
1126 | 1.84k | switch(*p){ |
1127 | 96 | param_common_cases; |
1128 | 661 | default: |
1129 | 661 | v=p; |
1130 | 661 | state=URI_VAL_P; |
1131 | 1.84k | } |
1132 | 1.80k | break; |
1133 | | |
1134 | | /* r2 */ |
1135 | 16.8k | param_switch1(PR2_R, '2', PR2_2_FIN); |
1136 | 16.6k | case PR2_2_FIN: |
1137 | 3.63k | switch(*p){ |
1138 | 82 | case '@': |
1139 | 82 | still_at_user; |
1140 | 43 | break; |
1141 | 1.72k | case '=': |
1142 | 1.72k | state=PR2_eq; |
1143 | 1.72k | break; |
1144 | 499 | semicolon_case; |
1145 | 499 | uri->r2.s=b; |
1146 | 499 | uri->r2.len=(p-b); |
1147 | 499 | break; |
1148 | 127 | question_case; |
1149 | 127 | uri->r2.s=b; |
1150 | 127 | uri->r2.len=(p-b); |
1151 | 127 | break; |
1152 | 623 | colon_case; |
1153 | 623 | break; |
1154 | 582 | default: |
1155 | 582 | state=URI_PARAM_P; |
1156 | 3.63k | } |
1157 | 3.59k | break; |
1158 | | /* handle r2=something case */ |
1159 | 3.59k | case PR2_eq: |
1160 | 1.70k | param=&uri->r2; |
1161 | 1.70k | param_val=&uri->r2_val; |
1162 | 1.70k | switch(*p){ |
1163 | 96 | param_common_cases; |
1164 | 542 | default: |
1165 | 542 | v=p; |
1166 | 542 | state=URI_VAL_P; |
1167 | 1.70k | } |
1168 | 1.66k | break; |
1169 | | |
1170 | | |
1171 | | /* gr */ |
1172 | 12.7k | param_switch(PG_G, 'r', 'R', PG_G_FIN); |
1173 | 12.6k | case PG_G_FIN: |
1174 | 8.27k | switch(*p){ |
1175 | 110 | case '@': |
1176 | 110 | still_at_user; |
1177 | 57 | break; |
1178 | 1.96k | case '=': |
1179 | 1.96k | state=PG_eq; |
1180 | 1.96k | break; |
1181 | 931 | semicolon_case; |
1182 | 931 | uri->gr.s=b; |
1183 | 931 | uri->gr.len=(p-b); |
1184 | 931 | break; |
1185 | 130 | question_case; |
1186 | 130 | uri->gr.s=b; |
1187 | 130 | uri->gr.len=(p-b); |
1188 | 130 | break; |
1189 | 1.66k | colon_case; |
1190 | 1.66k | break; |
1191 | 3.47k | default: |
1192 | 3.47k | state=URI_PARAM_P; |
1193 | 8.27k | } |
1194 | 8.21k | break; |
1195 | | /* handle gr=something case */ |
1196 | 8.21k | case PG_eq: |
1197 | 1.94k | param=&uri->gr; |
1198 | 1.94k | param_val=&uri->gr_val; |
1199 | 1.94k | switch(*p){ |
1200 | 96 | param_common_cases; |
1201 | 721 | default: |
1202 | 721 | v=p; |
1203 | 721 | state=URI_VAL_P; |
1204 | 1.94k | } |
1205 | 1.91k | break; |
1206 | | |
1207 | | |
1208 | | /* pn-* */ |
1209 | 141k | param_switch(PN_P, 'n', 'N', PN_N); |
1210 | 141k | param_switch1(PN_N, '-', PN_dash); |
1211 | 118k | param_switch(PN_dash, 'p', 'P', PN_P2); |
1212 | | |
1213 | 107k | param_switch_bigger(PN_P2, 'r', 'R', 'a', 'A', 'u', 'U', |
1214 | 100k | PN_PR, PN3_A, PN4_U); |
1215 | 99.9k | param_switch_big(PN_PR, 'o', 'O', 'i', 'I', PN1_O, PN2_I); |
1216 | | |
1217 | | /* pn-provider */ |
1218 | 74.2k | param_switch(PN1_O, 'v', 'V', PN1_V); |
1219 | 56.2k | param_switch(PN1_V, 'i', 'I', PN1_I); |
1220 | 50.3k | param_switch(PN1_I, 'd', 'D', PN1_D); |
1221 | 46.5k | param_switch(PN1_D, 'e', 'E', PN1_E); |
1222 | 41.4k | param_switch(PN1_E, 'r', 'R', PN1_FIN); |
1223 | 35.0k | case PN1_FIN: |
1224 | 32.4k | param=&uri->pn_provider; |
1225 | 32.4k | switch(*p){ |
1226 | 96 | case '@': |
1227 | 96 | still_at_user; |
1228 | 57 | break; |
1229 | 30.2k | case '=': |
1230 | 30.2k | state=PN1_eq; |
1231 | 30.2k | break; |
1232 | 828 | semicolon_case; |
1233 | 828 | uri->pn_provider.s=b; |
1234 | 828 | uri->pn_provider.len=(p-b); |
1235 | 828 | break; |
1236 | 106 | question_case; |
1237 | 106 | uri->pn_provider.s=b; |
1238 | 106 | uri->pn_provider.len=(p-b); |
1239 | 106 | break; |
1240 | 471 | colon_case; |
1241 | 471 | break; |
1242 | 644 | default: |
1243 | 644 | state=URI_PARAM_P; |
1244 | 32.4k | } |
1245 | 32.3k | break; |
1246 | | /* handle pn-provider=something case */ |
1247 | 32.3k | case PN1_eq: |
1248 | 30.2k | param=&uri->pn_provider; |
1249 | 30.2k | param_val=&uri->pn_provider_val; |
1250 | 30.2k | switch(*p){ |
1251 | 62 | param_common_cases; |
1252 | 19.3k | default: |
1253 | 19.3k | v=p; |
1254 | 19.3k | state=URI_VAL_P; |
1255 | 30.2k | } |
1256 | 30.2k | break; |
1257 | | |
1258 | | /* pn-prid */ |
1259 | 30.2k | param_switch(PN2_I, 'd', 'D', PN2_D); |
1260 | 10.5k | param_xswitch1(PN2_D, '=', PN2_eq); |
1261 | 2.20k | case PN2_eq: |
1262 | 2.16k | param=&uri->pn_prid; |
1263 | 2.16k | param_val=&uri->pn_prid_val; |
1264 | 2.16k | switch(*p){ |
1265 | 82 | param_common_cases; |
1266 | 715 | default: |
1267 | 715 | v=p; |
1268 | 715 | state=URI_VAL_P; |
1269 | 2.16k | } |
1270 | 2.12k | break; |
1271 | | |
1272 | | /* pn-param */ |
1273 | 10.3k | param_switch(PN3_A, 'r', 'R', PN3_R); |
1274 | 10.2k | param_switch(PN3_R, 'a', 'A', PN3_A2); |
1275 | 7.45k | param_switch(PN3_A2, 'm', 'M', PN3_M); |
1276 | 4.74k | param_xswitch1(PN3_M, '=', PN3_eq); |
1277 | 2.14k | case PN3_eq: |
1278 | 2.08k | param=&uri->pn_param; |
1279 | 2.08k | param_val=&uri->pn_param_val; |
1280 | 2.08k | switch(*p){ |
1281 | 96 | param_common_cases; |
1282 | 498 | default: |
1283 | 498 | v=p; |
1284 | 498 | state=URI_VAL_P; |
1285 | 2.08k | } |
1286 | 2.03k | break; |
1287 | | |
1288 | | /* pn-purr */ |
1289 | 9.98k | param_switch(PN4_U, 'r', 'R', PN4_R); |
1290 | 9.94k | param_switch(PN4_R, 'r', 'R', PN4_R2); |
1291 | 5.07k | param_xswitch1(PN4_R2, '=', PN4_eq); |
1292 | 2.11k | case PN4_eq: |
1293 | 2.05k | param=&uri->pn_purr; |
1294 | 2.05k | param_val=&uri->pn_purr_val; |
1295 | 2.05k | switch(*p){ |
1296 | 82 | param_common_cases; |
1297 | 442 | default: |
1298 | 442 | v=p; |
1299 | 442 | state=URI_VAL_P; |
1300 | 2.05k | } |
1301 | 2.01k | break; |
1302 | | |
1303 | | |
1304 | 66.0k | case URI_HEADERS: |
1305 | | /* for now nobody needs them so we completely ignore the |
1306 | | * headers (they are not allowed in request uri) --andrei */ |
1307 | 66.0k | switch(*p){ |
1308 | 6.79k | case '@': |
1309 | | /* yak, we are still at user */ |
1310 | 6.79k | still_at_user; |
1311 | 4.35k | break; |
1312 | 13.5k | case ';': |
1313 | | /* we might be still parsing user, try it */ |
1314 | 13.5k | if (found_user) goto error_bad_char; |
1315 | 6.38k | error_headers=1; /* if this is not the user |
1316 | | we have an error */ |
1317 | | /* if pass is set => it cannot be user:pass |
1318 | | * => error (';') is illegal in a header */ |
1319 | 6.38k | if (pass) goto error_headers; |
1320 | 6.28k | break; |
1321 | 6.28k | case ':': |
1322 | 3.03k | if (found_user==0){ |
1323 | | /*might be pass but only if user not found yet*/ |
1324 | 1.68k | if (pass){ |
1325 | 66 | found_user=1; /* no user */ |
1326 | 66 | pass=0; |
1327 | 1.61k | }else{ |
1328 | 1.61k | pass=p; |
1329 | 1.61k | } |
1330 | 1.68k | } |
1331 | 3.03k | break; |
1332 | 1.59k | case '?': |
1333 | 1.59k | if (pass){ |
1334 | 52 | found_user=1; /* no user, pass cannot contain '?'*/ |
1335 | 52 | pass=0; |
1336 | 52 | } |
1337 | 1.59k | break; |
1338 | 66.0k | } |
1339 | 56.3k | break; |
1340 | 56.3k | default: |
1341 | 0 | goto error_bug; |
1342 | 6.46M | } |
1343 | 6.46M | } |
1344 | | |
1345 | | /*end of uri */ |
1346 | 27.5k | switch (state){ |
1347 | 77 | case URI_INIT: /* error empty uri */ |
1348 | 77 | goto error_too_short; |
1349 | 87 | case URI_USER: |
1350 | | /* this is the host, it can't be the user */ |
1351 | 87 | if (found_user) goto error_bad_uri; |
1352 | 87 | uri->host.s=s; |
1353 | 87 | uri->host.len=p-s; |
1354 | 87 | state=URI_HOST; |
1355 | 87 | break; |
1356 | 3.34k | case URI_PASSWORD: |
1357 | | /* this is the port, it can't be the passwd */ |
1358 | 3.34k | if (found_user) goto error_bad_port; |
1359 | 3.34k | if (port_no > USHRT_MAX) goto error_bad_port; |
1360 | 295 | uri->port.s=s; |
1361 | 295 | uri->port.len=p-s; |
1362 | 295 | uri->port_no=port_no; |
1363 | 295 | uri->host=uri->user; |
1364 | 295 | uri->user.s=0; |
1365 | 295 | uri->user.len=0; |
1366 | 295 | break; |
1367 | 965 | case URI_PASSWORD_ALPHA: |
1368 | | /* this is the port, it can't be the passwd */ |
1369 | 965 | goto error_bad_port; |
1370 | 514 | case URI_HOST_P: |
1371 | 536 | case URI_HOST6_END: |
1372 | 536 | uri->host.s=s; |
1373 | 536 | uri->host.len=p-s; |
1374 | 536 | break; |
1375 | 7.71k | case URI_HOST: /* error: null host */ |
1376 | 7.85k | case URI_HOST6_P: /* error: unterminated ipv6 reference*/ |
1377 | 7.85k | goto error_bad_host; |
1378 | 393 | case URI_PORT: |
1379 | 393 | uri->port.s=s; |
1380 | 393 | uri->port.len=p-s; |
1381 | 393 | uri->port_no=port_no; |
1382 | 393 | break; |
1383 | 1.90k | case URI_PARAM: |
1384 | 4.51k | case URI_PARAM_P: |
1385 | 4.58k | case URI_PARAM_VAL_P: |
1386 | 4.58k | u_param_set(b, v); |
1387 | | /* intermediate param states */ |
1388 | 4.63k | case PT_T: /* transport */ |
1389 | 4.66k | case PT_R: |
1390 | 4.70k | case PT_A: |
1391 | 4.73k | case PT_N: |
1392 | 4.75k | case PT_S: |
1393 | 4.78k | case PT_P: |
1394 | 4.81k | case PT_O: |
1395 | 4.83k | case PT_R2: |
1396 | 4.86k | case PT_T2: |
1397 | 4.88k | case PT_eq: /* ignore empty transport params */ |
1398 | 4.91k | case PTTL_T2: /* ttl */ |
1399 | 4.94k | case PTTL_L: |
1400 | 4.95k | case PTTL_eq: |
1401 | 5.00k | case PU_U: /* user */ |
1402 | 5.02k | case PU_S: |
1403 | 5.05k | case PU_E: |
1404 | 5.07k | case PU_R: |
1405 | 5.09k | case PU_eq: |
1406 | 5.13k | case PM_M: /* method */ |
1407 | 5.17k | case PM_E: |
1408 | 5.20k | case PM_T: |
1409 | 5.22k | case PM_H: |
1410 | 5.25k | case PM_O: |
1411 | 5.28k | case PM_D: |
1412 | 5.30k | case PM_eq: |
1413 | 5.34k | case PLR_L: /* lr */ |
1414 | 5.38k | case PR2_R: /* r2 */ |
1415 | 5.41k | case PG_G: /* gr */ |
1416 | 5.41k | uri->params.s=s; |
1417 | 5.41k | uri->params.len=p-s; |
1418 | 5.41k | break; |
1419 | | /* fin param states */ |
1420 | 27 | case PLR_R_FIN: |
1421 | 43 | case PLR_eq: |
1422 | 43 | uri->params.s=s; |
1423 | 43 | uri->params.len=p-s; |
1424 | 43 | uri->lr.s=b; |
1425 | 43 | uri->lr.len=p-b; |
1426 | 43 | break; |
1427 | 16 | case PR2_2_FIN: |
1428 | 35 | case PR2_eq: |
1429 | 35 | uri->params.s=s; |
1430 | 35 | uri->params.len=p-s; |
1431 | 35 | uri->r2.s=b; |
1432 | 35 | uri->r2.len=p-b; |
1433 | 35 | break; |
1434 | 32 | case PG_G_FIN: |
1435 | 49 | case PG_eq: |
1436 | 49 | uri->params.s=s; |
1437 | 49 | uri->params.len=p-s; |
1438 | 49 | uri->gr.s=b; |
1439 | 49 | uri->gr.len=p-b; |
1440 | 49 | break; |
1441 | 25 | case PN1_FIN: |
1442 | 35 | case PN1_eq: |
1443 | 35 | uri->params.s=s; |
1444 | 35 | uri->params.len=p-s; |
1445 | 35 | uri->pn_provider.s=b; |
1446 | 35 | uri->pn_provider.len=p-b; |
1447 | 35 | break; |
1448 | 700 | case URI_VAL_P: |
1449 | | /* intermediate value states */ |
1450 | 727 | case VU_U: |
1451 | 752 | case VU_D: |
1452 | 772 | case VT_T: |
1453 | 798 | case VT_C: |
1454 | 821 | case VTLS_L: |
1455 | 844 | case VS_S: |
1456 | 870 | case VS_C: |
1457 | 897 | case VW_W: |
1458 | 918 | case VS_T: |
1459 | 918 | uri->params.s=s; |
1460 | 918 | uri->params.len=p-s; |
1461 | 918 | param_set(b, v); |
1462 | 918 | break; |
1463 | | /* fin value states */ |
1464 | 27 | case VU_P_FIN: |
1465 | 27 | uri->params.s=s; |
1466 | 27 | uri->params.len=p-s; |
1467 | 27 | param_set(b, v); |
1468 | 27 | uri->proto=PROTO_UDP; |
1469 | 27 | break; |
1470 | 27 | case VT_P_FIN: |
1471 | 27 | uri->params.s=s; |
1472 | 27 | uri->params.len=p-s; |
1473 | 27 | param_set(b, v); |
1474 | 27 | uri->proto=PROTO_TCP; |
1475 | 27 | break; |
1476 | 26 | case VTLS_S_FIN: |
1477 | 26 | uri->params.s=s; |
1478 | 26 | uri->params.len=p-s; |
1479 | 26 | param_set(b, v); |
1480 | 26 | uri->proto=PROTO_TLS; |
1481 | 26 | break; |
1482 | 25 | case VS_P_FIN: |
1483 | 25 | uri->params.s=s; |
1484 | 25 | uri->params.len=p-s; |
1485 | 25 | param_set(b, v); |
1486 | 25 | uri->proto=PROTO_SCTP; |
1487 | 25 | break; |
1488 | 26 | case VW_S: |
1489 | 26 | case VW_S_FIN: |
1490 | 26 | uri->params.s=s; |
1491 | 26 | uri->params.len=p-s; |
1492 | 26 | param_set(b, v); |
1493 | 26 | uri->proto=PROTO_WS; |
1494 | 26 | break; |
1495 | 27 | case VWS_S_FIN: |
1496 | 27 | uri->params.s=s; |
1497 | 27 | uri->params.len=p-s; |
1498 | 27 | param_set(b, v); |
1499 | 27 | uri->proto=PROTO_WSS; |
1500 | 27 | break; |
1501 | | /* headers */ |
1502 | 6.31k | case URI_HEADERS: |
1503 | 6.31k | uri->headers.s=s; |
1504 | 6.31k | uri->headers.len=p-s; |
1505 | 6.31k | if (error_headers) goto error_headers; |
1506 | 1.93k | break; |
1507 | | /* intermediate PN param states */ |
1508 | 1.93k | case PN_P: |
1509 | 87 | case PN_N: |
1510 | 106 | case PN_dash: |
1511 | 135 | case PN_P2: |
1512 | 163 | case PN_PR: |
1513 | 187 | case PN1_O: |
1514 | 213 | case PN1_V: |
1515 | 241 | case PN1_I: |
1516 | 267 | case PN1_D: |
1517 | 291 | case PN1_E: |
1518 | 318 | case PN2_I: |
1519 | 346 | case PN3_A: |
1520 | 371 | case PN3_R: |
1521 | 398 | case PN3_A2: |
1522 | 423 | case PN4_U: |
1523 | 447 | case PN4_R: |
1524 | 447 | uri->params.s=s; |
1525 | 447 | uri->params.len=p-s; |
1526 | 447 | break; |
1527 | 121 | case PN2_D: |
1528 | 162 | case PN2_eq: |
1529 | 210 | case PN3_M: |
1530 | 270 | case PN3_eq: |
1531 | 341 | case PN4_R2: |
1532 | 399 | case PN4_eq: |
1533 | 399 | goto error_bad_uri; |
1534 | 479 | default: |
1535 | 479 | goto error_bug; |
1536 | 27.5k | } |
1537 | 10.3k | switch(uri->type){ |
1538 | 4.53k | case TEL_URI_T: |
1539 | 4.53k | case TELS_URI_T: |
1540 | | /* fix tel uris, move the number in uri and empty the host */ |
1541 | 4.53k | uri->user=uri->host; |
1542 | | /* TEL does not have a host part, still most of the code expects |
1543 | | * one, so lets keep the pointer, but set a 0 length */ |
1544 | 4.53k | uri->host.len=0; |
1545 | 4.53k | break; |
1546 | 5.74k | case SIP_URI_T: |
1547 | 5.77k | case SIPS_URI_T: |
1548 | 5.78k | case URN_SERVICE_URI_T: |
1549 | | /* nothing to do for these URIs */ |
1550 | 5.78k | break; |
1551 | 16 | case URN_NENA_SERVICE_URI_T: |
1552 | 16 | uri->user.s=0; |
1553 | 16 | uri->user.len=0; |
1554 | | /* keep the service name as host part */ |
1555 | 16 | break; |
1556 | 0 | case ERROR_URI_T: |
1557 | 0 | LM_ERR("unexpected error (BUG?)\n"); |
1558 | 0 | goto error_bad_uri; |
1559 | 0 | break; /* do nothing, avoids a compilation warning */ |
1560 | 10.3k | } |
1561 | | #ifdef EXTRA_DEBUG |
1562 | | /* do stuff */ |
1563 | | LM_DBG("parsed uri:\n type=%d user=<%.*s>(%d)\n passwd=<%.*s>(%d)\n" |
1564 | | " host=<%.*s>(%d)\n port=<%.*s>(%d): %d\n params=<%.*s>(%d)\n" |
1565 | | " headers=<%.*s>(%d)\n", |
1566 | | uri->type, |
1567 | | uri->user.len, ZSW(uri->user.s), uri->user.len, |
1568 | | uri->passwd.len, ZSW(uri->passwd.s), uri->passwd.len, |
1569 | | uri->host.len, ZSW(uri->host.s), uri->host.len, |
1570 | | uri->port.len, ZSW(uri->port.s), uri->port.len, uri->port_no, |
1571 | | uri->params.len, ZSW(uri->params.s), uri->params.len, |
1572 | | uri->headers.len, ZSW(uri->headers.s), uri->headers.len |
1573 | | ); |
1574 | | LM_DBG(" uri params:\n transport=<%.*s>, val=<%.*s>, proto=%d\n", |
1575 | | uri->transport.len, ZSW(uri->transport.s), uri->transport_val.len, |
1576 | | ZSW(uri->transport_val.s), uri->proto); |
1577 | | LM_DBG(" user-param=<%.*s>, val=<%.*s>\n", |
1578 | | uri->user_param.len, ZSW(uri->user_param.s), |
1579 | | uri->user_param_val.len, ZSW(uri->user_param_val.s)); |
1580 | | LM_DBG(" method=<%.*s>, val=<%.*s>\n", |
1581 | | uri->method.len, ZSW(uri->method.s), |
1582 | | uri->method_val.len, ZSW(uri->method_val.s)); |
1583 | | LM_DBG(" ttl=<%.*s>, val=<%.*s>\n", |
1584 | | uri->ttl.len, ZSW(uri->ttl.s), |
1585 | | uri->ttl_val.len, ZSW(uri->ttl_val.s)); |
1586 | | LM_DBG(" maddr=<%.*s>, val=<%.*s>\n", |
1587 | | uri->maddr.len, ZSW(uri->maddr.s), |
1588 | | uri->maddr_val.len, ZSW(uri->maddr_val.s)); |
1589 | | LM_DBG(" lr=<%.*s>, val=<%.*s>\n", uri->lr.len, ZSW(uri->lr.s), |
1590 | | uri->lr_val.len, ZSW(uri->lr_val.s)); |
1591 | | LM_DBG(" r2=<%.*s>, val=<%.*s>\n", uri->r2.len, ZSW(uri->r2.s), |
1592 | | uri->r2_val.len, ZSW(uri->r2_val.s)); |
1593 | | for(i=0; i<URI_MAX_U_PARAMS && uri->u_name[i].s; i++) |
1594 | | LM_DBG("uname=[%p]-><%.*s> uval=[%p]-><%.*s>\n", |
1595 | | uri->u_name[i].s, uri->u_name[i].len, uri->u_name[i].s, |
1596 | | uri->u_val[i].s, uri->u_val[i].len, uri->u_val[i].s); |
1597 | | if (i!=uri->u_params_no) |
1598 | | LM_ERR("inconsisten # of u_name:[%d]!=[%d]\n", i, uri->u_params_no); |
1599 | | #endif |
1600 | 10.3k | return 0; |
1601 | | |
1602 | 76.3k | error_too_short: |
1603 | 76.3k | LM_ERR("uri too short: <%.*s> (%d)\n", |
1604 | 76.3k | len, ZSW(buf), len); |
1605 | 76.3k | goto error_exit; |
1606 | 25.3k | error_bad_char: |
1607 | 25.3k | LM_ERR("bad char '%c' in state %d" |
1608 | 25.3k | " parsed: <%.*s> (%d) / <%.*s> (%d)\n", |
1609 | 25.3k | p < end ? *p : *(buf+len-1), state, (int)(p-buf), ZSW(buf), |
1610 | 0 | (int)(p-buf), len, ZSW(buf), len); |
1611 | 25.3k | goto error_exit; |
1612 | 10.1k | error_bad_host: |
1613 | 10.1k | LM_ERR("bad host in uri (error at char %c in" |
1614 | 10.1k | " state %d) parsed: <%.*s>(%d) /<%.*s> (%d)\n", |
1615 | 10.1k | p < end ? *p : *(buf+len-1), state, (int)(p-buf), ZSW(buf), |
1616 | 0 | (int)(p-buf), len, ZSW(buf), len); |
1617 | 10.1k | goto error_exit; |
1618 | 6.39k | error_bad_port: |
1619 | 6.39k | LM_ERR("bad port in uri (error at char '%c' in" |
1620 | 6.39k | " state %d) parsed: <%.*s>(%d) /<%.*s> (%d)\n", |
1621 | 6.39k | p < end ? *p : *(buf+len-1), state, (int)(p-buf), ZSW(buf), |
1622 | 0 | (int)(p-buf), len, ZSW(buf), len); |
1623 | 6.39k | goto error_exit; |
1624 | 6.09k | error_bad_uri: |
1625 | 6.09k | LM_ERR("bad uri, state %d parsed: <%.*s> (%d) / <%.*s> (%d)\n", |
1626 | 6.09k | state, (int)(p-buf), ZSW(buf), (int)(p-buf), len, |
1627 | 0 | ZSW(buf), len); |
1628 | 6.09k | goto error_exit; |
1629 | 4.48k | error_headers: |
1630 | 4.48k | LM_ERR("bad uri headers: <%.*s>(%d) / <%.*s>(%d)\n", |
1631 | 4.48k | uri->headers.len, ZSW(uri->headers.s), uri->headers.len, |
1632 | 0 | len, ZSW(buf), len); |
1633 | 4.48k | goto error_exit; |
1634 | 479 | error_bug: |
1635 | 479 | LM_ERR("bad state %d parsed: <%.*s> (%d) / <%.*s> (%d)\n", |
1636 | 479 | state, (int)(p-buf), ZSW(buf), (int)(p-buf), len, ZSW(buf), len); |
1637 | 129k | error_exit: |
1638 | 129k | ser_error=E_BAD_URI; |
1639 | 129k | uri->type=ERROR_URI_T; |
1640 | 129k | update_stat(bad_URIs, 1); |
1641 | 129k | return E_BAD_URI; |
1642 | 479 | } |
1643 | | |
1644 | | |
1645 | | int parse_sip_msg_uri(struct sip_msg* msg) |
1646 | 71.4k | { |
1647 | 71.4k | char* tmp; |
1648 | 71.4k | int tmp_len; |
1649 | 71.4k | if (msg->parsed_uri_ok) return 1; |
1650 | | |
1651 | 71.4k | if (msg->new_uri.s){ |
1652 | 0 | tmp=msg->new_uri.s; |
1653 | 0 | tmp_len=msg->new_uri.len; |
1654 | 71.4k | }else{ |
1655 | 71.4k | tmp=msg->first_line.u.request.uri.s; |
1656 | 71.4k | tmp_len=msg->first_line.u.request.uri.len; |
1657 | 71.4k | } |
1658 | 71.4k | if (parse_uri(tmp, tmp_len, &msg->parsed_uri)<0){ |
1659 | 69.5k | LM_ERR("bad uri <%.*s>\n", tmp_len, tmp); |
1660 | 69.5k | msg->parsed_uri_ok=0; |
1661 | 69.5k | set_err_info(OSER_EC_PARSER, OSER_EL_MEDIUM, "error parsing r-uri"); |
1662 | 69.5k | set_err_reply(400, "bad r-uri"); |
1663 | 69.5k | return -1; |
1664 | 69.5k | } |
1665 | 1.94k | msg->parsed_uri_ok=1; |
1666 | 1.94k | return 0; |
1667 | 71.4k | } |
1668 | | |
1669 | | |
1670 | | int parse_orig_ruri(struct sip_msg* msg) |
1671 | 54.0k | { |
1672 | 54.0k | str *uri; |
1673 | | |
1674 | 54.0k | if (msg->parsed_orig_ruri_ok) |
1675 | 0 | return 1; |
1676 | | |
1677 | 54.0k | uri = &REQ_LINE(msg).uri; |
1678 | | |
1679 | 54.0k | if (parse_uri(uri->s, uri->len, &msg->parsed_orig_ruri)<0) { |
1680 | 52.1k | LM_ERR("bad uri <%.*s>\n", uri->len, ZSW(uri->s)); |
1681 | 52.1k | msg->parsed_orig_ruri_ok = 0; |
1682 | 52.1k | set_err_info(OSER_EC_PARSER, OSER_EL_MEDIUM, |
1683 | 52.1k | "error parsing incoming uri"); |
1684 | 52.1k | set_err_reply(400, "bad i-uri"); |
1685 | 52.1k | return -1; |
1686 | 52.1k | } |
1687 | | |
1688 | 1.94k | msg->parsed_orig_ruri_ok = 1; |
1689 | 1.94k | return 0; |
1690 | 54.0k | } |
1691 | | |
1692 | | #define compare_uri_val(field,cmpfunc) \ |
1693 | 0 | do { \ |
1694 | 0 | if (first.field.len != second.field.len) \ |
1695 | 0 | { \ |
1696 | 0 | LM_DBG("Different URI field - " #field "\n"); \ |
1697 | 0 | return 1; \ |
1698 | 0 | } \ |
1699 | 0 | else \ |
1700 | 0 | { \ |
1701 | 0 | if (first.field.len != 0) \ |
1702 | 0 | if (cmpfunc(first.field.s,second.field.s,first.field.len)) \ |
1703 | 0 | { \ |
1704 | 0 | LM_DBG("Different URI field - " #field "\n"); \ |
1705 | 0 | return 1; \ |
1706 | 0 | } \ |
1707 | 0 | } \ |
1708 | 0 | } while (0) |
1709 | | |
1710 | | /* Compare 2 SIP URIs according to RFC 3261 |
1711 | | * |
1712 | | * Return value : 0 if URIs match |
1713 | | * 1 if URIs don't match |
1714 | | * -1 if errors have occurred |
1715 | | */ |
1716 | | int compare_uris(str *raw_uri_a,struct sip_uri* parsed_uri_a, |
1717 | | str *raw_uri_b,struct sip_uri *parsed_uri_b) |
1718 | 0 | { |
1719 | 0 | #define UNESCAPED_BUF_LEN 1024 |
1720 | 0 | char unescaped_a[UNESCAPED_BUF_LEN], unescaped_b[UNESCAPED_BUF_LEN]; |
1721 | |
|
1722 | 0 | str unescaped_userA={unescaped_a, UNESCAPED_BUF_LEN}; |
1723 | 0 | str unescaped_userB={unescaped_b, UNESCAPED_BUF_LEN}; |
1724 | |
|
1725 | 0 | struct sip_uri first; |
1726 | 0 | struct sip_uri second; |
1727 | 0 | char matched[URI_MAX_U_PARAMS]; |
1728 | 0 | int i,j; |
1729 | |
|
1730 | 0 | if ( (!raw_uri_a && !parsed_uri_a) || (!raw_uri_b && !parsed_uri_b) ) |
1731 | 0 | { |
1732 | 0 | LM_ERR("Provide either a raw or parsed form of a SIP URI\n"); |
1733 | 0 | return -1; |
1734 | 0 | } |
1735 | | |
1736 | 0 | if (raw_uri_a && raw_uri_b) |
1737 | 0 | { |
1738 | | |
1739 | | /* maybe we're lucky and straight-forward comparison succeeds */ |
1740 | 0 | if (raw_uri_a->len == raw_uri_b->len) |
1741 | 0 | if (strncasecmp(raw_uri_a->s,raw_uri_b->s,raw_uri_a->len) == 0) |
1742 | 0 | { |
1743 | 0 | LM_DBG("straight-forward URI match\n"); |
1744 | 0 | if (parse_uri(raw_uri_a->s,raw_uri_a->len,&first) < 0) |
1745 | 0 | { |
1746 | 0 | LM_ERR("Failed to parse first URI\n"); |
1747 | 0 | return -1; |
1748 | 0 | } |
1749 | 0 | if (parse_uri(raw_uri_b->s,raw_uri_b->len,&second) < 0) |
1750 | 0 | { |
1751 | 0 | LM_ERR("Failed to parse second URI\n"); |
1752 | 0 | return -1; |
1753 | 0 | } |
1754 | 0 | if (unescape_user(&first.user, &unescaped_userA) < 0 || |
1755 | 0 | unescape_user(&second.user, &unescaped_userB) < 0) { |
1756 | 0 | LM_ERR("Failed to unescape user!\n"); |
1757 | 0 | return -1; |
1758 | 0 | } |
1759 | 0 | first.user = unescaped_userA; |
1760 | 0 | second.user = unescaped_userB; |
1761 | 0 | compare_uri_val(user,strncmp); |
1762 | 0 | compare_uri_val(passwd,strncmp); |
1763 | 0 | return 0; |
1764 | 0 | } |
1765 | 0 | } |
1766 | | |
1767 | | /* XXX - maybe if we have two parsed sip_uris, |
1768 | | * or only one parsed and one raw, |
1769 | | * it should be possible to do a straight-forward |
1770 | | * URI match ? */ |
1771 | | |
1772 | 0 | if (parsed_uri_a) |
1773 | 0 | first = *parsed_uri_a; |
1774 | 0 | else |
1775 | 0 | { |
1776 | 0 | if (parse_uri(raw_uri_a->s,raw_uri_a->len,&first) < 0) |
1777 | 0 | { |
1778 | 0 | LM_ERR("Failed to parse first URI\n"); |
1779 | 0 | return -1; |
1780 | 0 | } |
1781 | 0 | } |
1782 | | |
1783 | 0 | if (parsed_uri_b) |
1784 | 0 | second = *parsed_uri_b; |
1785 | 0 | else |
1786 | 0 | { |
1787 | 0 | if (parse_uri(raw_uri_b->s,raw_uri_b->len,&second) < 0) |
1788 | 0 | { |
1789 | 0 | LM_ERR("Failed to parse second URI\n"); |
1790 | 0 | return -1; |
1791 | 0 | } |
1792 | 0 | } |
1793 | | |
1794 | 0 | if (first.type != second.type) |
1795 | 0 | { |
1796 | 0 | LM_DBG("Different uri types\n"); |
1797 | 0 | return 1; |
1798 | 0 | } |
1799 | | |
1800 | 0 | if (unescape_user(&first.user, &unescaped_userA) < 0 || |
1801 | 0 | unescape_user(&second.user, &unescaped_userB) < 0) { |
1802 | 0 | LM_ERR("Failed to unescape user!\n"); |
1803 | 0 | return -1; |
1804 | 0 | } |
1805 | | |
1806 | 0 | first.user = unescaped_userA; |
1807 | 0 | second.user = unescaped_userB; |
1808 | |
|
1809 | 0 | compare_uri_val(user,strncmp); |
1810 | 0 | compare_uri_val(passwd,strncmp); |
1811 | 0 | compare_uri_val(host,strncasecmp); |
1812 | 0 | compare_uri_val(port,strncmp); |
1813 | | |
1814 | 0 | compare_uri_val(transport_val,strncasecmp); |
1815 | 0 | compare_uri_val(ttl_val,strncasecmp); |
1816 | 0 | compare_uri_val(user_param_val,strncasecmp); |
1817 | 0 | compare_uri_val(maddr_val,strncasecmp); |
1818 | 0 | compare_uri_val(method_val,strncasecmp); |
1819 | 0 | compare_uri_val(lr_val,strncasecmp); |
1820 | 0 | compare_uri_val(r2_val,strncasecmp); |
1821 | | |
1822 | 0 | if (first.u_params_no == 0 || second.u_params_no == 0) |
1823 | | /* one URI doesn't have other params, |
1824 | | * automatically all unknown params in other URI match |
1825 | | */ |
1826 | 0 | goto headers_check; |
1827 | | |
1828 | 0 | memset(matched,0,URI_MAX_U_PARAMS); |
1829 | |
|
1830 | 0 | for (i=0;i<first.u_params_no;i++) |
1831 | 0 | for (j=0;j<second.u_params_no;j++) |
1832 | 0 | if (matched[j] == 0 && |
1833 | 0 | (first.u_name[i].len == second.u_name[j].len && |
1834 | 0 | strncasecmp(first.u_name[i].s,second.u_name[j].s, |
1835 | 0 | first.u_name[i].len) == 0)) |
1836 | 0 | { |
1837 | | /* point of no return - matching unknown parameter values */ |
1838 | 0 | if (first.u_val[i].len != second.u_val[j].len) |
1839 | 0 | { |
1840 | 0 | LM_DBG("Different URI param value for param %.*s\n", |
1841 | 0 | first.u_name[i].len,first.u_name[i].s); |
1842 | 0 | return 1; |
1843 | 0 | } |
1844 | 0 | else |
1845 | 0 | { |
1846 | 0 | if (first.u_val[i].len == 0) |
1847 | 0 | { |
1848 | | /* no value for unknown params - match */ |
1849 | 0 | matched[j] = 1; |
1850 | 0 | break; |
1851 | 0 | } |
1852 | | |
1853 | 0 | if (strncasecmp(first.u_val[i].s,second.u_val[j].s, |
1854 | 0 | second.u_val[j].len)) |
1855 | 0 | { |
1856 | 0 | LM_DBG("Different URI param value for param %.*s\n", |
1857 | 0 | first.u_name[i].len,first.u_name[i].s); |
1858 | 0 | return 1; |
1859 | 0 | } |
1860 | 0 | else |
1861 | 0 | { |
1862 | 0 | matched[j] = 1; |
1863 | 0 | break; |
1864 | 0 | } |
1865 | 0 | } |
1866 | 0 | } |
1867 | | |
1868 | | /* got here, it means all unknown params in first URI have been resolved |
1869 | | => first URI matched second URI, and the other way around |
1870 | | */ |
1871 | | |
1872 | 0 | headers_check: |
1873 | | /* XXX Do we really care ? */ |
1874 | 0 | compare_uri_val(headers,strncasecmp); |
1875 | 0 | return 0; |
1876 | 0 | } |