/src/kamailio/src/core/action.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * |
3 | | * Copyright (C) 2001-2003 FhG Fokus |
4 | | * |
5 | | * This file is part of Kamailio, a free SIP server. |
6 | | * |
7 | | * SPDX-License-Identifier: GPL-2.0-or-later |
8 | | * |
9 | | * Kamailio is free software; you can redistribute it and/or modify |
10 | | * it under the terms of the GNU General Public License as published by |
11 | | * the Free Software Foundation; either version 2 of the License, or |
12 | | * (at your option) any later version |
13 | | * |
14 | | * Kamailio is distributed in the hope that it will be useful, |
15 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
17 | | * GNU General Public License for more details. |
18 | | * |
19 | | * You should have received a copy of the GNU General Public License |
20 | | * along with this program; if not, write to the Free Software |
21 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
22 | | * |
23 | | */ |
24 | | |
25 | | /*! |
26 | | * \file |
27 | | * \brief Kamailio core :: Config file actions |
28 | | * \ingroup core |
29 | | * Module: \ref core |
30 | | */ |
31 | | |
32 | | |
33 | | #include "comp_defs.h" |
34 | | |
35 | | #include "action.h" |
36 | | #include "config.h" |
37 | | #include "error.h" |
38 | | #include "dprint.h" |
39 | | #include "proxy.h" |
40 | | #include "forward.h" |
41 | | #include "udp_server.h" |
42 | | #include "route.h" |
43 | | #include "parser/msg_parser.h" |
44 | | #include "parser/parse_uri.h" |
45 | | #include "ut.h" |
46 | | #include "lvalue.h" |
47 | | #include "sr_module.h" |
48 | | #include "select_buf.h" |
49 | | #include "mem/mem.h" |
50 | | #include "globals.h" |
51 | | #include "dset.h" |
52 | | #include "onsend.h" |
53 | | #include "fmsg.h" |
54 | | #include "resolve.h" |
55 | | #ifdef USE_TCP |
56 | | #include "tcp_server.h" |
57 | | #endif |
58 | | #ifdef USE_SCTP |
59 | | #include "sctp_core.h" |
60 | | #endif |
61 | | #include "switch.h" |
62 | | #include "events.h" |
63 | | #include "cfg/cfg_struct.h" |
64 | | |
65 | | #include <sys/types.h> |
66 | | #include <sys/socket.h> |
67 | | #include <netdb.h> |
68 | | #include <stdlib.h> |
69 | | #include <netinet/in.h> |
70 | | #include <arpa/inet.h> |
71 | | #include <string.h> |
72 | | |
73 | | |
74 | | #ifdef DEBUG_DMALLOC |
75 | | #include <dmalloc.h> |
76 | | #endif |
77 | | |
78 | | int _last_returned_code = 0; |
79 | | |
80 | | /* current action executed from config file */ |
81 | | static cfg_action_t *_cfg_crt_action = 0; |
82 | | |
83 | | /*!< maximum number of recursive calls for blocks of actions */ |
84 | | static unsigned int max_recursive_level = 256; |
85 | | |
86 | | void set_max_recursive_level(unsigned int lev) |
87 | 0 | { |
88 | 0 | max_recursive_level = lev; |
89 | 0 | } |
90 | | |
91 | | /* return current action executed from config file */ |
92 | | cfg_action_t *get_cfg_crt_action(void) |
93 | 0 | { |
94 | 0 | return _cfg_crt_action; |
95 | 0 | } |
96 | | |
97 | | /* return line in config for current executed action */ |
98 | | int get_cfg_crt_line(void) |
99 | 0 | { |
100 | 0 | if(_cfg_crt_action == 0) |
101 | 0 | return 0; |
102 | 0 | return _cfg_crt_action->cline; |
103 | 0 | } |
104 | | |
105 | | /* return name of config for current executed action */ |
106 | | char *get_cfg_crt_file_name(void) |
107 | 0 | { |
108 | 0 | if(_cfg_crt_action == 0) |
109 | 0 | return 0; |
110 | 0 | return _cfg_crt_action->cfile; |
111 | 0 | } |
112 | | |
113 | | /* return name of routing block for current executed action */ |
114 | | char *get_cfg_crt_route_name(void) |
115 | 0 | { |
116 | 0 | if(_cfg_crt_action == 0) |
117 | 0 | return 0; |
118 | 0 | return _cfg_crt_action->rname; |
119 | 0 | } |
120 | | |
121 | | /* handle the exit code of a module function call. |
122 | | * (used internally in do_action()) |
123 | | * @param h - script handle (h->last_retcode and h->run_flags will be set). |
124 | | * @param ret - module function (v0 or v2) retcode |
125 | | * Side-effects: sets _last_returned_code |
126 | | */ |
127 | | #define MODF_HANDLE_RETCODE(h, ret) \ |
128 | 0 | do { \ |
129 | 0 | /* if (unlikely((ret)==0)) (h)->run_flags|=EXIT_R_F; */ \ |
130 | 0 | (h)->run_flags |= EXIT_R_F & (((ret) != 0) - 1); \ |
131 | 0 | (h)->last_retcode = (ret); \ |
132 | 0 | _last_returned_code = (h)->last_retcode; \ |
133 | 0 | } while(0) |
134 | | |
135 | | |
136 | | /* frees parameters converted using MODF_RVE_PARAM_CONVERT() from dst. |
137 | | * (used internally in do_action()) |
138 | | * Assumes src is unchanged. |
139 | | * Side-effects: clobbers i (int). |
140 | | */ |
141 | | #define MODF_RVE_PARAM_FREE(cmd, src, dst) \ |
142 | 0 | for(i = 0; i < (dst)[1].u.number; i++) { \ |
143 | 0 | if((src)[i + 2].type == RVE_ST && (dst)[i + 2].u.data) { \ |
144 | 0 | if((dst)[i + 2].type == RVE_FREE_FIXUP_ST) { \ |
145 | 0 | /* call free_fixup (which should restore the original |
146 | 0 | string) */ \ |
147 | 0 | (void)call_fixup( \ |
148 | 0 | (cmd)->free_fixup, &(dst)[i + 2].u.data, i + 1); \ |
149 | 0 | } else if((dst)[i + 2].type == FPARAM_DYN_ST) { \ |
150 | 0 | /* completely frees fparam and restore original string */ \ |
151 | 0 | fparam_free_restore(&(dst)[i + 2].u.data); \ |
152 | 0 | } \ |
153 | 0 | /* free allocated string */ \ |
154 | 0 | pkg_free((dst)[i + 2].u.data); \ |
155 | 0 | (dst)[i + 2].u.data = 0; \ |
156 | 0 | } \ |
157 | 0 | } |
158 | | |
159 | | |
160 | | /* fills dst from src, converting RVE_ST params to STRING_ST. |
161 | | * (used internally in do_action()) |
162 | | * @param src - source action_u_t array, as in the action structure |
163 | | * @param dst - destination action_u_t array, will be filled from src. |
164 | | * WARNING: dst must be cleaned when done, use MODULE_RVE_PARAM_FREE() |
165 | | * Side-effects: clobbers i (int), s (str), rv (rvalue*), might jump to error. |
166 | | */ |
167 | | #define MODF_RVE_PARAM_CONVERT(h, msg, cmd, src, dst) \ |
168 | 0 | do { \ |
169 | 0 | (dst)[1] = (src)[1]; \ |
170 | 0 | for(i = 0; i < (src)[1].u.number; i++) { \ |
171 | 0 | if((src)[2 + i].type == RVE_ST) { \ |
172 | 0 | rv = rval_expr_eval((h), (msg), (src)[i + 2].u.data); \ |
173 | 0 | if(unlikely(rv == 0 \ |
174 | 0 | || rval_get_str((h), (msg), &s, rv, 0) < 0)) { \ |
175 | 0 | rval_destroy(rv); \ |
176 | 0 | ERR("failed to convert RVE to string\n"); \ |
177 | 0 | (dst)[1].u.number = i; \ |
178 | 0 | MODF_RVE_PARAM_FREE(cmd, src, dst); \ |
179 | 0 | goto error; \ |
180 | 0 | } \ |
181 | 0 | (dst)[i + 2].type = STRING_RVE_ST; \ |
182 | 0 | (dst)[i + 2].u.string = s.s; \ |
183 | 0 | (dst)[i + 2].u.str.len = s.len; \ |
184 | 0 | rval_destroy(rv); \ |
185 | 0 | if((cmd)->fixup) { \ |
186 | 0 | if((cmd)->free_fixup) { \ |
187 | 0 | if(likely(call_fixup((cmd)->fixup, \ |
188 | 0 | &(dst)[i + 2].u.data, i + 1) \ |
189 | 0 | >= 0)) { \ |
190 | 0 | /* success => mark it for calling free fixup */ \ |
191 | 0 | if(likely((dst)[i + 2].u.data != s.s)) \ |
192 | 0 | (dst)[i + 2].type = RVE_FREE_FIXUP_ST; \ |
193 | 0 | } else { \ |
194 | 0 | /* error calling fixup => mark conv. parameter \ |
195 | 0 | and return error */ \ |
196 | 0 | (dst)[1].u.number = i; \ |
197 | 0 | ERR("runtime fixup failed for %s param %d\n", \ |
198 | 0 | (cmd)->name, i + 1); \ |
199 | 0 | MODF_RVE_PARAM_FREE(cmd, src, dst); \ |
200 | 0 | goto error; \ |
201 | 0 | } \ |
202 | 0 | } else if((cmd)->fixup_flags & FIXUP_F_FPARAM_RVE) { \ |
203 | 0 | if(likely(call_fixup((cmd)->fixup, \ |
204 | 0 | &(dst)[i + 2].u.data, i + 1) \ |
205 | 0 | >= 0)) { \ |
206 | 0 | if((dst)[i + 2].u.data != s.s) \ |
207 | 0 | (dst)[i + 2].type = FPARAM_DYN_ST; \ |
208 | 0 | } else { \ |
209 | 0 | /* error calling fixup => mark conv. parameter \ |
210 | 0 | and return error */ \ |
211 | 0 | (dst)[1].u.number = i; \ |
212 | 0 | ERR("runtime fixup failed for %s param %d\n", \ |
213 | 0 | (cmd)->name, i + 1); \ |
214 | 0 | MODF_RVE_PARAM_FREE(cmd, src, dst); \ |
215 | 0 | goto error; \ |
216 | 0 | } \ |
217 | 0 | } \ |
218 | 0 | } \ |
219 | 0 | } else \ |
220 | 0 | (dst)[i + 2] = (src)[i + 2]; \ |
221 | 0 | } \ |
222 | 0 | } while(0) |
223 | | |
224 | | |
225 | | /* call a module function with normal STRING_ST params. |
226 | | * (used internally in do_action()) |
227 | | * @param f_type - cmd_function type |
228 | | * @param h |
229 | | * @param msg |
230 | | * @param src - source action_u_t array (e.g. action->val) |
231 | | * @param params... - variable list of parameters, passed to the module |
232 | | * function |
233 | | * Side-effects: sets ret, clobbers i (int), s (str), rv (rvalue*), cmd, |
234 | | * might jump to error. |
235 | | * |
236 | | */ |
237 | | #ifdef __SUNPRO_C |
238 | | #define MODF_CALL(f_type, h, msg, src, ...) \ |
239 | | do { \ |
240 | | cmd = (src)[0].u.data; \ |
241 | | ret = ((f_type)cmd->function)((msg), __VA_ARGS__); \ |
242 | | MODF_HANDLE_RETCODE(h, ret); \ |
243 | | } while(0) |
244 | | #else /* ! __SUNPRO_C (gcc, icc a.s.o) */ |
245 | | #define MODF_CALL(f_type, h, msg, src, params...) \ |
246 | 0 | do { \ |
247 | 0 | cmd = (src)[0].u.data; \ |
248 | 0 | ret = ((f_type)cmd->function)((msg), ##params); \ |
249 | 0 | MODF_HANDLE_RETCODE(h, ret); \ |
250 | 0 | } while(0) |
251 | | #endif /* __SUNPRO_C */ |
252 | | |
253 | | |
254 | | /* call a module function with possible RVE params. |
255 | | * (used internally in do_action()) |
256 | | * @param f_type - cmd_function type |
257 | | * @param h |
258 | | * @param msg |
259 | | * @param src - source action_u_t array (e.g. action->val) |
260 | | * @param dst - temporary action_u_t array used for conversions. It can be |
261 | | * used for the function parameters. Its contents is not |
262 | | * valid after the call. |
263 | | * @param params... - variable list of parameters, passed to the module |
264 | | * function |
265 | | * Side-effects: sets ret, clobbers i (int), s (str), rv (rvalue*), f, dst, |
266 | | * might jump to error. |
267 | | * |
268 | | */ |
269 | | #ifdef __SUNPRO_C |
270 | | #define MODF_RVE_CALL(f_type, h, msg, src, dst, ...) \ |
271 | | do { \ |
272 | | cmd = (src)[0].u.data; \ |
273 | | MODF_RVE_PARAM_CONVERT(h, msg, cmd, src, dst); \ |
274 | | ret = ((f_type)cmd->function)((msg), __VA_ARGS__); \ |
275 | | MODF_HANDLE_RETCODE(h, ret); \ |
276 | | /* free strings allocated by us or fixups */ \ |
277 | | MODF_RVE_PARAM_FREE(cmd, src, dst); \ |
278 | | } while(0) |
279 | | #else /* ! __SUNPRO_C (gcc, icc a.s.o) */ |
280 | | #define MODF_RVE_CALL(f_type, h, msg, src, dst, params...) \ |
281 | 0 | do { \ |
282 | 0 | cmd = (src)[0].u.data; \ |
283 | 0 | MODF_RVE_PARAM_CONVERT(h, msg, cmd, src, dst); \ |
284 | 0 | ret = ((f_type)cmd->function)((msg), ##params); \ |
285 | 0 | MODF_HANDLE_RETCODE(h, ret); \ |
286 | 0 | /* free strings allocated by us or fixups */ \ |
287 | 0 | MODF_RVE_PARAM_FREE(cmd, src, dst); \ |
288 | 0 | } while(0) |
289 | | #endif /* __SUNPRO_C */ |
290 | | |
291 | | |
292 | | /* ret= 0! if action -> end of list(e.g DROP), |
293 | | > 0 to continue processing next actions |
294 | | and <0 on error */ |
295 | | int do_action(struct run_act_ctx *h, struct action *a, struct sip_msg *msg) |
296 | 0 | { |
297 | 0 | int ret; |
298 | 0 | long li; |
299 | 0 | long v; |
300 | 0 | struct dest_info dst; |
301 | 0 | char *tmp; |
302 | 0 | char *new_uri, *end, *crt; |
303 | 0 | ksr_cmd_export_t *cmd; |
304 | 0 | int len; |
305 | 0 | int user; |
306 | 0 | struct sip_uri uri, next_hop; |
307 | 0 | struct sip_uri *u; |
308 | 0 | unsigned short port; |
309 | 0 | str *dst_host; |
310 | 0 | int i, flags; |
311 | 0 | avp_t *avp; |
312 | 0 | struct search_state st; |
313 | 0 | struct switch_cond_table *sct; |
314 | 0 | struct switch_jmp_table *sjt; |
315 | 0 | struct rval_expr *rve; |
316 | 0 | struct match_cond_table *mct; |
317 | 0 | struct rvalue *rv; |
318 | 0 | struct rvalue *rv1; |
319 | 0 | struct rval_cache c1; |
320 | 0 | str s; |
321 | 0 | void *srevp[2]; |
322 | 0 | sr_event_param_t evp = {0}; |
323 | | |
324 | | /* temporary storage space for a struct action.val[] working copy |
325 | | (needed to transform RVE intro STRING before calling module |
326 | | functions). [0] is not used (corresp. to the module export pointer), |
327 | | [1] contains the number of params, and [2..] the param values. |
328 | | We need [1], because some fixup function use it |
329 | | (see fixup_get_param_count()). */ |
330 | 0 | static action_u_t mod_f_params[MAX_ACTIONS]; |
331 | | |
332 | | /* reset the value of error to E_UNSPEC so avoid unknowledgable |
333 | | functions to return with error (status<0) and not setting it |
334 | | leaving there previous error; cache the previous value though |
335 | | for functions which want to process it */ |
336 | 0 | prev_ser_error = ser_error; |
337 | 0 | ser_error = E_UNSPEC; |
338 | | |
339 | | /* hook for every executed action (in use by cfg debugger) */ |
340 | 0 | if(unlikely(sr_event_enabled(SREV_CFG_RUN_ACTION))) { |
341 | 0 | srevp[0] = (void *)a; |
342 | 0 | srevp[1] = (void *)msg; |
343 | 0 | evp.data = (void *)srevp; |
344 | 0 | sr_event_exec(SREV_CFG_RUN_ACTION, &evp); |
345 | 0 | } |
346 | |
|
347 | 0 | ret = E_BUG; |
348 | 0 | switch((unsigned char)a->type) { |
349 | 0 | case DROP_T: |
350 | 0 | switch(a->val[0].type) { |
351 | 0 | case NUMBER_ST: |
352 | 0 | ret = (int)a->val[0].u.number; |
353 | 0 | break; |
354 | 0 | case RVE_ST: |
355 | 0 | rve = (struct rval_expr *)a->val[0].u.data; |
356 | 0 | if(rval_expr_eval_long(h, msg, &li, rve) < 0) { |
357 | 0 | LM_WARN("failed to eval int expression\n"); |
358 | 0 | } |
359 | 0 | ret = (int)li; |
360 | 0 | break; |
361 | 0 | case RETCODE_ST: |
362 | 0 | ret = h->last_retcode; |
363 | 0 | break; |
364 | 0 | default: |
365 | 0 | BUG("unexpected subtype %d in DROP_T\n", a->val[0].type); |
366 | 0 | ret = 0; |
367 | 0 | goto error; |
368 | 0 | } |
369 | 0 | h->run_flags |= (unsigned int)a->val[1].u.number; |
370 | 0 | if(unlikely((ret == 0) && (h->run_flags & RETURN_R_F))) { |
371 | 0 | h->run_flags |= EXIT_R_F; |
372 | 0 | } |
373 | 0 | break; |
374 | 0 | case FORWARD_T: |
375 | 0 | #ifdef USE_TCP |
376 | 0 | case FORWARD_TCP_T: |
377 | 0 | #endif |
378 | 0 | #ifdef USE_TLS |
379 | 0 | case FORWARD_TLS_T: |
380 | 0 | #endif |
381 | 0 | #ifdef USE_SCTP |
382 | 0 | case FORWARD_SCTP_T: |
383 | 0 | #endif |
384 | 0 | case FORWARD_UDP_T: |
385 | | /* init dst */ |
386 | 0 | init_dest_info(&dst); |
387 | 0 | if(a->type == FORWARD_UDP_T) |
388 | 0 | dst.proto = PROTO_UDP; |
389 | 0 | #ifdef USE_TCP |
390 | 0 | else if(a->type == FORWARD_TCP_T) { |
391 | 0 | dst.proto = PROTO_TCP; |
392 | 0 | if(msg->msg_flags & FL_USE_OTCPID) { |
393 | 0 | dst.id = msg->otcpid; |
394 | 0 | } |
395 | 0 | } |
396 | 0 | #endif |
397 | 0 | #ifdef USE_TLS |
398 | 0 | else if(a->type == FORWARD_TLS_T) { |
399 | 0 | dst.proto = PROTO_TLS; |
400 | 0 | if(msg->msg_flags & FL_USE_OTCPID) { |
401 | 0 | dst.id = msg->otcpid; |
402 | 0 | } |
403 | 0 | } |
404 | 0 | #endif |
405 | 0 | #ifdef USE_SCTP |
406 | 0 | else if(a->type == FORWARD_SCTP_T) |
407 | 0 | dst.proto = PROTO_SCTP; |
408 | 0 | #endif |
409 | 0 | else |
410 | 0 | dst.proto = PROTO_NONE; |
411 | 0 | if(a->val[0].type == URIHOST_ST) { |
412 | | /*parse uri*/ |
413 | |
|
414 | 0 | if(msg->dst_uri.len) { |
415 | 0 | ret = parse_uri( |
416 | 0 | msg->dst_uri.s, msg->dst_uri.len, &next_hop); |
417 | 0 | u = &next_hop; |
418 | 0 | } else { |
419 | 0 | ret = parse_sip_msg_uri(msg); |
420 | 0 | u = &msg->parsed_uri; |
421 | 0 | } |
422 | |
|
423 | 0 | if(ret < 0) { |
424 | 0 | LM_ERR("forward: bad_uri dropping packet\n"); |
425 | 0 | goto error; |
426 | 0 | } |
427 | | |
428 | 0 | switch(a->val[1].type) { |
429 | 0 | case URIPORT_ST: |
430 | 0 | port = u->port_no; |
431 | 0 | break; |
432 | 0 | case NUMBER_ST: |
433 | 0 | port = a->val[1].u.number; |
434 | 0 | break; |
435 | 0 | default: |
436 | 0 | LM_CRIT("bad forward 2nd param type (%d)\n", |
437 | 0 | a->val[1].type); |
438 | 0 | ret = E_UNSPEC; |
439 | 0 | goto error_fwd_uri; |
440 | 0 | } |
441 | 0 | if(dst.proto == PROTO_NONE) { /* only if proto not set get it |
442 | | from the uri */ |
443 | 0 | switch(u->proto) { |
444 | 0 | case PROTO_NONE: |
445 | | /*dst.proto=PROTO_UDP; */ |
446 | | /* no proto, try to get it from the dns */ |
447 | 0 | break; |
448 | 0 | case PROTO_UDP: |
449 | 0 | #ifdef USE_TCP |
450 | 0 | case PROTO_TCP: |
451 | 0 | case PROTO_WS: |
452 | 0 | #endif |
453 | 0 | #ifdef USE_TLS |
454 | 0 | case PROTO_TLS: |
455 | 0 | case PROTO_WSS: |
456 | 0 | #endif |
457 | 0 | #ifdef USE_SCTP |
458 | 0 | case PROTO_SCTP: |
459 | 0 | #endif |
460 | 0 | dst.proto = u->proto; |
461 | 0 | break; |
462 | 0 | default: |
463 | 0 | LM_ERR("forward: bad uri transport %d\n", u->proto); |
464 | 0 | ret = E_BAD_PROTO; |
465 | 0 | goto error_fwd_uri; |
466 | 0 | } |
467 | 0 | #ifdef USE_TLS |
468 | 0 | if(u->type == SIPS_URI_T) { |
469 | 0 | if(u->proto == PROTO_UDP) { |
470 | 0 | LM_ERR("forward: secure uri incompatible with " |
471 | 0 | "transport %d\n", |
472 | 0 | u->proto); |
473 | 0 | ret = E_BAD_PROTO; |
474 | 0 | goto error_fwd_uri; |
475 | 0 | } else if(u->proto != PROTO_WSS) |
476 | 0 | dst.proto = PROTO_TLS; |
477 | 0 | else |
478 | 0 | dst.proto = PROTO_WSS; |
479 | 0 | } |
480 | 0 | #endif |
481 | 0 | } |
482 | | |
483 | | #ifdef HONOR_MADDR |
484 | | if(u->maddr_val.s && u->maddr_val.len) |
485 | | dst_host = &u->maddr_val; |
486 | | else |
487 | | #endif |
488 | 0 | dst_host = &u->host; |
489 | | #ifdef USE_COMP |
490 | | dst.comp = u->comp; |
491 | | #endif |
492 | 0 | ret = forward_request(msg, dst_host, port, &dst); |
493 | 0 | if(ret >= 0) { |
494 | 0 | ret = 1; |
495 | 0 | } |
496 | 0 | } else if((a->val[0].type == PROXY_ST) |
497 | 0 | && (a->val[1].type == NUMBER_ST)) { |
498 | 0 | if(dst.proto == PROTO_NONE) |
499 | 0 | dst.proto = msg->rcv.proto; |
500 | 0 | proxy2su(&dst.to, (struct proxy_l *)a->val[0].u.data); |
501 | 0 | ret = forward_request(msg, 0, 0, &dst); |
502 | 0 | if(ret >= 0) { |
503 | 0 | ret = 1; |
504 | 0 | proxy_mark((struct proxy_l *)a->val[0].u.data, ret); |
505 | 0 | } else if(ser_error != E_OK) { |
506 | 0 | proxy_mark((struct proxy_l *)a->val[0].u.data, ret); |
507 | 0 | } |
508 | 0 | } else { |
509 | 0 | LM_CRIT("bad forward() types %d, %d\n", a->val[0].type, |
510 | 0 | a->val[1].type); |
511 | 0 | ret = E_BUG; |
512 | 0 | goto error; |
513 | 0 | } |
514 | 0 | break; |
515 | 0 | case LOG_T: |
516 | 0 | if((a->val[0].type != NUMBER_ST) || (a->val[1].type != STRING_ST)) { |
517 | 0 | LM_CRIT("bad log() parameter types %d, %d\n", a->val[0].type, |
518 | 0 | a->val[1].type); |
519 | 0 | ret = E_BUG; |
520 | 0 | goto error; |
521 | 0 | } |
522 | 0 | LOG_FN(DEFAULT_FACILITY, a->val[0].u.number, "<script>: ", "%s", |
523 | 0 | a->val[1].u.string); |
524 | 0 | ret = 1; |
525 | 0 | break; |
526 | | |
527 | | /* jku -- introduce a new branch */ |
528 | 0 | case APPEND_BRANCH_T: |
529 | 0 | if(unlikely(a->val[0].type != STR_ST)) { |
530 | 0 | LM_CRIT("bad append_branch_t %d\n", a->val[0].type); |
531 | 0 | ret = E_BUG; |
532 | 0 | goto error; |
533 | 0 | } |
534 | 0 | getbflagsval(0, (flag_t *)&flags); |
535 | 0 | ret = append_branch(msg, &a->val[0].u.str, &msg->dst_uri, |
536 | 0 | &msg->path_vec, a->val[1].u.number, (flag_t)flags, |
537 | 0 | msg->force_send_socket, 0, 0, 0, 0); |
538 | | /* if the uri is the ruri and q was also not changed, mark |
539 | | ruri as consumed, to avoid having an identical branch */ |
540 | 0 | if((a->val[0].u.str.s == 0 || a->val[0].u.str.len == 0) |
541 | 0 | && a->val[1].u.number == Q_UNSPECIFIED) |
542 | 0 | ruri_mark_consumed(); |
543 | 0 | break; |
544 | | |
545 | | /* remove last branch */ |
546 | 0 | case REMOVE_BRANCH_T: |
547 | 0 | if(a->val[0].type != NUMBER_ST) { |
548 | 0 | ret = drop_sip_branch(0) ? -1 : 1; |
549 | 0 | } else { |
550 | 0 | ret = drop_sip_branch(a->val[0].u.number) ? -1 : 1; |
551 | 0 | } |
552 | 0 | break; |
553 | | |
554 | | /* remove all branches */ |
555 | 0 | case CLEAR_BRANCHES_T: |
556 | 0 | clear_branches(); |
557 | 0 | ret = 1; |
558 | 0 | break; |
559 | | |
560 | | /* jku begin: is_length_greater_than */ |
561 | 0 | case LEN_GT_T: |
562 | 0 | if(a->val[0].type != NUMBER_ST) { |
563 | 0 | LM_CRIT("bad len_gt type %d\n", a->val[0].type); |
564 | 0 | ret = E_BUG; |
565 | 0 | goto error; |
566 | 0 | } |
567 | | /* LM_DBG("message length %d, max %d\n", |
568 | | msg->len, a->val[0].u.number ); */ |
569 | 0 | ret = msg->len >= a->val[0].u.number ? 1 : -1; |
570 | 0 | break; |
571 | | /* jku end: is_length_greater_than */ |
572 | | |
573 | | /* jku - begin : flag processing */ |
574 | | |
575 | 0 | case SETFLAG_T: |
576 | 0 | if(a->val[0].type != NUMBER_ST) { |
577 | 0 | LM_CRIT("bad setflag() type %d\n", a->val[0].type); |
578 | 0 | ret = E_BUG; |
579 | 0 | goto error; |
580 | 0 | } |
581 | 0 | if(!flag_in_range(a->val[0].u.number)) { |
582 | 0 | ret = E_CFG; |
583 | 0 | goto error; |
584 | 0 | } |
585 | 0 | setflag(msg, a->val[0].u.number); |
586 | 0 | ret = 1; |
587 | 0 | break; |
588 | | |
589 | 0 | case RESETFLAG_T: |
590 | 0 | if(a->val[0].type != NUMBER_ST) { |
591 | 0 | LM_CRIT("bad resetflag() type %d\n", a->val[0].type); |
592 | 0 | ret = E_BUG; |
593 | 0 | goto error; |
594 | 0 | } |
595 | 0 | if(!flag_in_range(a->val[0].u.number)) { |
596 | 0 | ret = E_CFG; |
597 | 0 | goto error; |
598 | 0 | } |
599 | 0 | resetflag(msg, a->val[0].u.number); |
600 | 0 | ret = 1; |
601 | 0 | break; |
602 | | |
603 | 0 | case ISFLAGSET_T: |
604 | 0 | if(a->val[0].type != NUMBER_ST) { |
605 | 0 | LM_CRIT("bad isflagset() type %d\n", a->val[0].type); |
606 | 0 | ret = E_BUG; |
607 | 0 | goto error; |
608 | 0 | } |
609 | 0 | if(!flag_in_range(a->val[0].u.number)) { |
610 | 0 | ret = E_CFG; |
611 | 0 | goto error; |
612 | 0 | } |
613 | 0 | ret = isflagset(msg, a->val[0].u.number); |
614 | 0 | break; |
615 | | /* jku - end : flag processing */ |
616 | | |
617 | 0 | case AVPFLAG_OPER_T: |
618 | 0 | ret = 0; |
619 | 0 | if((a->val[0].u.attr->type & AVP_INDEX_ALL) == AVP_INDEX_ALL |
620 | 0 | || (a->val[0].u.attr->type & AVP_NAME_RE) != 0) { |
621 | 0 | for(avp = search_first_avp(a->val[0].u.attr->type, |
622 | 0 | a->val[0].u.attr->name, NULL, &st); |
623 | 0 | avp; avp = search_next_avp(&st, NULL)) { |
624 | 0 | switch(a->val[2].u.number) { |
625 | | /* oper: 0..reset, 1..set, -1..no change */ |
626 | 0 | case 0: |
627 | 0 | avp->flags &= ~(avp_flags_t)a->val[1].u.number; |
628 | 0 | break; |
629 | 0 | case 1: |
630 | 0 | avp->flags |= (avp_flags_t)a->val[1].u.number; |
631 | 0 | break; |
632 | 0 | default:; |
633 | 0 | } |
634 | 0 | ret = ret |
635 | 0 | || ((avp->flags & (avp_flags_t)a->val[1].u.number) |
636 | 0 | != 0); |
637 | 0 | } |
638 | 0 | } else { |
639 | 0 | avp = search_avp_by_index(a->val[0].u.attr->type, |
640 | 0 | a->val[0].u.attr->name, NULL, a->val[0].u.attr->index); |
641 | 0 | if(avp) { |
642 | 0 | switch(a->val[2].u.number) { |
643 | | /* oper: 0..reset, 1..set, -1..no change */ |
644 | 0 | case 0: |
645 | 0 | avp->flags &= ~(avp_flags_t)a->val[1].u.number; |
646 | 0 | break; |
647 | 0 | case 1: |
648 | 0 | avp->flags |= (avp_flags_t)a->val[1].u.number; |
649 | 0 | break; |
650 | 0 | default:; |
651 | 0 | } |
652 | 0 | ret = (avp->flags & (avp_flags_t)a->val[1].u.number) != 0; |
653 | 0 | } |
654 | 0 | } |
655 | 0 | if(ret == 0) |
656 | 0 | ret = -1; |
657 | 0 | break; |
658 | 0 | case ERROR_T: |
659 | 0 | if((a->val[0].type != STRING_ST) | (a->val[1].type != STRING_ST)) { |
660 | 0 | LM_CRIT("bad error() types %d, %d\n", a->val[0].type, |
661 | 0 | a->val[1].type); |
662 | 0 | ret = E_BUG; |
663 | 0 | goto error; |
664 | 0 | } |
665 | 0 | LM_NOTICE("error(\"%s\", \"%s\") " |
666 | 0 | "not implemented yet\n", |
667 | 0 | a->val[0].u.string, a->val[1].u.string); |
668 | 0 | ret = 1; |
669 | 0 | break; |
670 | 0 | case ROUTE_T: |
671 | 0 | if(likely(a->val[0].type == NUMBER_ST)) |
672 | 0 | i = a->val[0].u.number; |
673 | 0 | else if(a->val[0].type == RVE_ST) { |
674 | 0 | rv = rval_expr_eval(h, msg, a->val[0].u.data); |
675 | 0 | rval_cache_init(&c1); |
676 | 0 | if(unlikely(rv == 0 |
677 | 0 | || rval_get_tmp_str(h, msg, &s, rv, 0, &c1) < 0)) { |
678 | 0 | rval_destroy(rv); |
679 | 0 | rval_cache_clean(&c1); |
680 | 0 | ERR("failed to convert RVE to string\n"); |
681 | 0 | ret = E_UNSPEC; |
682 | 0 | goto error; |
683 | 0 | } |
684 | 0 | i = route_lookup(&main_rt, s.s); |
685 | 0 | if(unlikely(i < 0)) { |
686 | 0 | ERR("route \"%s\" not found at %s:%d\n", s.s, |
687 | 0 | (a->cfile) ? a->cfile : "line", a->cline); |
688 | 0 | rval_destroy(rv); |
689 | 0 | rval_cache_clean(&c1); |
690 | 0 | s.s = 0; |
691 | 0 | ret = E_SCRIPT; |
692 | 0 | goto error; |
693 | 0 | } |
694 | 0 | rval_destroy(rv); |
695 | 0 | rval_cache_clean(&c1); |
696 | 0 | s.s = 0; |
697 | 0 | } else { |
698 | 0 | LM_CRIT("bad route() type %d\n", a->val[0].type); |
699 | 0 | ret = E_BUG; |
700 | 0 | goto error; |
701 | 0 | } |
702 | 0 | if(unlikely((i >= main_rt.idx) || (i < 0))) { |
703 | 0 | LM_ERR("invalid routing table number in" |
704 | 0 | "route(%lu) at %s:%d\n", |
705 | 0 | a->val[0].u.number, (a->cfile) ? a->cfile : "line", |
706 | 0 | a->cline); |
707 | 0 | ret = E_CFG; |
708 | 0 | goto error; |
709 | 0 | } |
710 | | /*ret=((ret=run_actions(rlist[a->val[0].u.number],msg))<0)?ret:1;*/ |
711 | 0 | ret = run_actions(h, main_rt.rlist[i], msg); |
712 | 0 | h->last_retcode = ret; |
713 | 0 | _last_returned_code = h->last_retcode; |
714 | 0 | h->run_flags &= |
715 | 0 | ~(RETURN_R_F | BREAK_R_F); /* absorb return & break */ |
716 | 0 | break; |
717 | 0 | case EXEC_T: |
718 | 0 | if(a->val[0].type != STRING_ST) { |
719 | 0 | LM_CRIT("bad exec() type %d\n", a->val[0].type); |
720 | 0 | ret = E_BUG; |
721 | 0 | goto error; |
722 | 0 | } |
723 | 0 | LM_NOTICE("exec(\"%s\") not fully implemented," |
724 | 0 | " using dumb version...\n", |
725 | 0 | a->val[0].u.string); |
726 | 0 | ret = system(a->val[0].u.string); |
727 | 0 | if(ret != 0) { |
728 | 0 | LM_NOTICE("exec() returned %d\n", ret); |
729 | 0 | } |
730 | 0 | ret = 1; |
731 | 0 | break; |
732 | 0 | case REVERT_URI_T: |
733 | 0 | if(msg->new_uri.s) { |
734 | 0 | pkg_free(msg->new_uri.s); |
735 | 0 | msg->new_uri.len = 0; |
736 | 0 | msg->new_uri.s = 0; |
737 | 0 | msg->parsed_uri_ok = 0; /* invalidate current parsed uri*/ |
738 | 0 | ruri_mark_new(); /* available for forking */ |
739 | 0 | }; |
740 | 0 | ret = 1; |
741 | 0 | break; |
742 | 0 | case SET_HOST_T: |
743 | 0 | case SET_HOSTPORT_T: |
744 | 0 | case SET_HOSTPORTTRANS_T: |
745 | 0 | case SET_HOSTALL_T: |
746 | 0 | case SET_USER_T: |
747 | 0 | case SET_USERPASS_T: |
748 | 0 | case SET_PORT_T: |
749 | 0 | case SET_URI_T: |
750 | 0 | case PREFIX_T: |
751 | 0 | case STRIP_T: |
752 | 0 | case STRIP_TAIL_T: |
753 | 0 | case SET_USERPHONE_T: |
754 | 0 | user = 0; |
755 | 0 | if(a->type == STRIP_T || a->type == STRIP_TAIL_T) { |
756 | 0 | if(a->val[0].type != NUMBER_ST) { |
757 | 0 | LM_CRIT("bad set*() type %d\n", a->val[0].type); |
758 | 0 | ret = E_BUG; |
759 | 0 | goto error; |
760 | 0 | } |
761 | 0 | } else if(a->type != SET_USERPHONE_T) { |
762 | 0 | if(a->val[0].type != STRING_ST) { |
763 | 0 | LM_CRIT("bad set*() type %d\n", a->val[0].type); |
764 | 0 | ret = E_BUG; |
765 | 0 | goto error; |
766 | 0 | } |
767 | 0 | } |
768 | 0 | if(a->type == SET_URI_T) { |
769 | 0 | if(msg->new_uri.s) { |
770 | 0 | pkg_free(msg->new_uri.s); |
771 | 0 | msg->new_uri.len = 0; |
772 | 0 | } |
773 | 0 | msg->parsed_uri_ok = 0; |
774 | 0 | len = strlen(a->val[0].u.string); |
775 | 0 | msg->new_uri.s = pkg_malloc(len + 1); |
776 | 0 | if(msg->new_uri.s == 0) { |
777 | 0 | PKG_MEM_ERROR; |
778 | 0 | ret = E_OUT_OF_MEM; |
779 | 0 | goto error; |
780 | 0 | } |
781 | 0 | memcpy(msg->new_uri.s, a->val[0].u.string, len); |
782 | 0 | msg->new_uri.s[len] = 0; |
783 | 0 | msg->new_uri.len = len; |
784 | 0 | ruri_mark_new(); /* available for forking */ |
785 | |
|
786 | 0 | ret = 1; |
787 | 0 | break; |
788 | 0 | } |
789 | 0 | if(msg->parsed_uri_ok == 0) { |
790 | 0 | if(msg->new_uri.s) { |
791 | 0 | tmp = msg->new_uri.s; |
792 | 0 | len = msg->new_uri.len; |
793 | 0 | } else { |
794 | 0 | tmp = msg->first_line.u.request.uri.s; |
795 | 0 | len = msg->first_line.u.request.uri.len; |
796 | 0 | } |
797 | 0 | if(parse_uri(tmp, len, &uri) < 0) { |
798 | 0 | LM_ERR("bad uri <%s>, dropping packet\n", tmp); |
799 | 0 | ret = E_UNSPEC; |
800 | 0 | goto error; |
801 | 0 | } |
802 | 0 | } else { |
803 | 0 | uri = msg->parsed_uri; |
804 | 0 | } |
805 | | |
806 | | /* skip SET_USERPHONE_T action if the URI is already |
807 | | * a tel: or tels: URI, or contains the user=phone param */ |
808 | 0 | if((a->type == SET_USERPHONE_T) |
809 | 0 | && ((uri.type == TEL_URI_T) || (uri.type == TELS_URI_T) |
810 | 0 | || ((uri.user_param_val.len == 5) |
811 | 0 | && (memcmp(uri.user_param_val.s, "phone", 5) |
812 | 0 | == 0)))) { |
813 | 0 | ret = 1; |
814 | 0 | break; |
815 | 0 | } |
816 | | /* SET_PORT_T does not work with tel: URIs */ |
817 | 0 | if((a->type == SET_PORT_T) |
818 | 0 | && ((uri.type == TEL_URI_T) || (uri.type == TELS_URI_T)) |
819 | 0 | && ((uri.flags & URI_SIP_USER_PHONE) == 0)) { |
820 | 0 | LM_ERR("port number of a tel: URI cannot be set\n"); |
821 | 0 | ret = E_UNSPEC; |
822 | 0 | goto error; |
823 | 0 | } |
824 | | |
825 | 0 | new_uri = pkg_malloc(MAX_URI_SIZE); |
826 | 0 | if(new_uri == 0) { |
827 | 0 | PKG_MEM_ERROR; |
828 | 0 | ret = E_OUT_OF_MEM; |
829 | 0 | goto error; |
830 | 0 | } |
831 | 0 | end = new_uri + MAX_URI_SIZE; |
832 | 0 | crt = new_uri; |
833 | | /* begin copying */ |
834 | | /* Preserve the URI scheme unless the host part needs |
835 | | * to be rewritten, and the shceme is tel: or tels: */ |
836 | 0 | switch(uri.type) { |
837 | 0 | case SIP_URI_T: |
838 | 0 | len = s_sip.len; |
839 | 0 | tmp = s_sip.s; |
840 | 0 | break; |
841 | | |
842 | 0 | case SIPS_URI_T: |
843 | 0 | len = s_sips.len; |
844 | 0 | tmp = s_sips.s; |
845 | 0 | break; |
846 | | |
847 | 0 | case TEL_URI_T: |
848 | 0 | if((uri.flags & URI_SIP_USER_PHONE) |
849 | 0 | || (a->type == SET_HOST_T) |
850 | 0 | || (a->type == SET_HOSTPORT_T) |
851 | 0 | || (a->type == SET_HOSTPORTTRANS_T)) { |
852 | 0 | len = s_sip.len; |
853 | 0 | tmp = s_sip.s; |
854 | 0 | break; |
855 | 0 | } |
856 | 0 | len = s_tel.len; |
857 | 0 | tmp = s_tel.s; |
858 | 0 | break; |
859 | | |
860 | 0 | case TELS_URI_T: |
861 | 0 | if((uri.flags & URI_SIP_USER_PHONE) |
862 | 0 | || (a->type == SET_HOST_T) |
863 | 0 | || (a->type == SET_HOSTPORT_T) |
864 | 0 | || (a->type == SET_HOSTPORTTRANS_T)) { |
865 | 0 | len = s_sips.len; |
866 | 0 | tmp = s_sips.s; |
867 | 0 | break; |
868 | 0 | } |
869 | 0 | len = s_tels.len; |
870 | 0 | tmp = s_tels.s; |
871 | 0 | break; |
872 | | |
873 | 0 | default: |
874 | 0 | LM_ERR("Unsupported URI scheme (%d), reverted to sip:\n", |
875 | 0 | uri.type); |
876 | 0 | len = s_sip.len; |
877 | 0 | tmp = s_sip.s; |
878 | 0 | } |
879 | 0 | if(crt + len + 1 /* colon */ > end) |
880 | 0 | goto error_uri; |
881 | 0 | memcpy(crt, tmp, len); |
882 | 0 | crt += len; |
883 | 0 | *crt = ':'; |
884 | 0 | crt++; |
885 | | |
886 | | /* user */ |
887 | | |
888 | | /* prefix (-jiri) */ |
889 | 0 | if(a->type == PREFIX_T) { |
890 | 0 | tmp = a->val[0].u.string; |
891 | 0 | len = strlen(tmp); |
892 | 0 | if(crt + len > end) |
893 | 0 | goto error_uri; |
894 | 0 | memcpy(crt, tmp, len); |
895 | 0 | crt += len; |
896 | | /* whatever we had before, with prefix we have username |
897 | | now */ |
898 | 0 | user = 1; |
899 | 0 | } |
900 | | |
901 | 0 | if((a->type == SET_USER_T) || (a->type == SET_USERPASS_T)) { |
902 | 0 | tmp = a->val[0].u.string; |
903 | 0 | len = strlen(tmp); |
904 | 0 | } else if(a->type == STRIP_T) { |
905 | 0 | if(a->val[0].u.number > uri.user.len) { |
906 | 0 | LM_WARN("too long strip asked; deleting username: %lu of " |
907 | 0 | "<%.*s>\n", |
908 | 0 | a->val[0].u.number, uri.user.len, uri.user.s); |
909 | 0 | len = 0; |
910 | 0 | } else if(a->val[0].u.number == uri.user.len) { |
911 | 0 | len = 0; |
912 | 0 | } else { |
913 | 0 | tmp = uri.user.s + a->val[0].u.number; |
914 | 0 | len = uri.user.len - a->val[0].u.number; |
915 | 0 | } |
916 | 0 | } else if(a->type == STRIP_TAIL_T) { |
917 | 0 | if(a->val[0].u.number > uri.user.len) { |
918 | 0 | LM_WARN("too long strip_tail asked; " |
919 | 0 | " deleting username: %lu of <%.*s>\n", |
920 | 0 | a->val[0].u.number, uri.user.len, uri.user.s); |
921 | 0 | len = 0; |
922 | 0 | } else if(a->val[0].u.number == uri.user.len) { |
923 | 0 | len = 0; |
924 | 0 | } else { |
925 | 0 | tmp = uri.user.s; |
926 | 0 | len = uri.user.len - a->val[0].u.number; |
927 | 0 | } |
928 | 0 | } else { |
929 | 0 | tmp = uri.user.s; |
930 | 0 | len = uri.user.len; |
931 | 0 | } |
932 | |
|
933 | 0 | if(len) { |
934 | 0 | if(crt + len > end) |
935 | 0 | goto error_uri; |
936 | 0 | memcpy(crt, tmp, len); |
937 | 0 | crt += len; |
938 | 0 | user = 1; /* we have a user field so mark it */ |
939 | 0 | } |
940 | | |
941 | 0 | if(a->type == SET_USERPASS_T) |
942 | 0 | tmp = 0; |
943 | 0 | else |
944 | 0 | tmp = uri.passwd.s; |
945 | | /* passwd - keep it only if user is set */ |
946 | 0 | if(user && tmp) { |
947 | 0 | len = uri.passwd.len; |
948 | 0 | if(crt + len + 1 > end) |
949 | 0 | goto error_uri; |
950 | 0 | *crt = ':'; |
951 | 0 | crt++; |
952 | 0 | memcpy(crt, tmp, len); |
953 | 0 | crt += len; |
954 | 0 | } |
955 | | /* tel: URI parameters */ |
956 | 0 | if((uri.type == TEL_URI_T) || (uri.type == TELS_URI_T)) { |
957 | 0 | tmp = uri.params.s; |
958 | 0 | if(tmp) { |
959 | 0 | len = uri.params.len; |
960 | 0 | if(crt + len + 1 > end) |
961 | 0 | goto error_uri; |
962 | 0 | *crt = ';'; |
963 | 0 | crt++; |
964 | 0 | memcpy(crt, tmp, len); |
965 | 0 | crt += len; |
966 | 0 | } |
967 | 0 | } |
968 | | /* host */ |
969 | 0 | if((a->type == SET_HOST_T) || (a->type == SET_HOSTPORT_T) |
970 | 0 | || (a->type == SET_HOSTALL_T) |
971 | 0 | || (a->type == SET_HOSTPORTTRANS_T)) { |
972 | 0 | tmp = a->val[0].u.string; |
973 | 0 | if(tmp) |
974 | 0 | len = strlen(tmp); |
975 | 0 | else |
976 | 0 | len = 0; |
977 | 0 | } else if((uri.type == SIP_URI_T) || (uri.type == SIPS_URI_T) |
978 | 0 | || (uri.flags & URI_SIP_USER_PHONE)) { |
979 | 0 | tmp = uri.host.s; |
980 | 0 | len = uri.host.len; |
981 | 0 | } else { |
982 | 0 | tmp = 0; |
983 | 0 | } |
984 | 0 | if(tmp) { |
985 | 0 | if(user) { /* add @ */ |
986 | 0 | if(crt + 1 > end) |
987 | 0 | goto error_uri; |
988 | 0 | *crt = '@'; |
989 | 0 | crt++; |
990 | 0 | } |
991 | 0 | if(crt + len > end) |
992 | 0 | goto error_uri; |
993 | 0 | memcpy(crt, tmp, len); |
994 | 0 | crt += len; |
995 | 0 | } |
996 | 0 | if(a->type == SET_HOSTALL_T) |
997 | 0 | goto done_seturi; |
998 | | /* port */ |
999 | 0 | if((a->type == SET_HOSTPORT_T) || (a->type == SET_HOSTPORTTRANS_T)) |
1000 | 0 | tmp = 0; |
1001 | 0 | else if(a->type == SET_PORT_T) { |
1002 | 0 | tmp = a->val[0].u.string; |
1003 | 0 | if(tmp) { |
1004 | 0 | len = strlen(tmp); |
1005 | 0 | if(len == 0) |
1006 | 0 | tmp = 0; |
1007 | 0 | } else |
1008 | 0 | len = 0; |
1009 | 0 | } else { |
1010 | 0 | tmp = uri.port.s; |
1011 | 0 | len = uri.port.len; |
1012 | 0 | } |
1013 | 0 | if(tmp) { |
1014 | 0 | if(crt + len + 1 > end) |
1015 | 0 | goto error_uri; |
1016 | 0 | *crt = ':'; |
1017 | 0 | crt++; |
1018 | 0 | memcpy(crt, tmp, len); |
1019 | 0 | crt += len; |
1020 | 0 | } |
1021 | | /* params */ |
1022 | 0 | if((a->type == SET_HOSTPORTTRANS_T) && uri.sip_params.s |
1023 | 0 | && uri.transport.s) { |
1024 | | /* bypass the transport parameter */ |
1025 | 0 | if(uri.sip_params.s < uri.transport.s) { |
1026 | | /* there are parameters before transport */ |
1027 | 0 | len = uri.transport.s - uri.sip_params.s - 1; |
1028 | | /* ignore the ';' at the end */ |
1029 | 0 | if(crt + len + 1 > end) |
1030 | 0 | goto error_uri; |
1031 | 0 | *crt = ';'; |
1032 | 0 | crt++; |
1033 | 0 | memcpy(crt, uri.sip_params.s, len); |
1034 | 0 | crt += len; |
1035 | 0 | } |
1036 | 0 | len = (uri.sip_params.s + uri.sip_params.len) |
1037 | 0 | - (uri.transport.s + uri.transport.len); |
1038 | 0 | if(len > 0) { |
1039 | | /* there are parameters after transport */ |
1040 | 0 | if(crt + len > end) |
1041 | 0 | goto error_uri; |
1042 | 0 | tmp = uri.transport.s + uri.transport.len; |
1043 | 0 | memcpy(crt, tmp, len); |
1044 | 0 | crt += len; |
1045 | 0 | } |
1046 | 0 | } else { |
1047 | 0 | tmp = uri.sip_params.s; |
1048 | 0 | if(tmp) { |
1049 | 0 | len = uri.sip_params.len; |
1050 | 0 | if(crt + len + 1 > end) |
1051 | 0 | goto error_uri; |
1052 | 0 | *crt = ';'; |
1053 | 0 | crt++; |
1054 | 0 | memcpy(crt, tmp, len); |
1055 | 0 | crt += len; |
1056 | 0 | } |
1057 | 0 | } |
1058 | | /* Add the user=phone param if a tel: or tels: |
1059 | | * URI was converted to sip: or sips:. |
1060 | | * (host part of a tel/tels URI was set.) |
1061 | | * Or in case of sip: URI and SET_USERPHONE_T action */ |
1062 | 0 | if(((((uri.type == TEL_URI_T) || (uri.type == TELS_URI_T)) |
1063 | 0 | && ((uri.flags & URI_SIP_USER_PHONE) == 0)) |
1064 | 0 | && ((a->type == SET_HOST_T) |
1065 | 0 | || (a->type == SET_HOSTPORT_T) |
1066 | 0 | || (a->type == SET_HOSTPORTTRANS_T))) |
1067 | 0 | || (a->type == SET_USERPHONE_T)) { |
1068 | 0 | tmp = ";user=phone"; |
1069 | 0 | len = strlen(tmp); |
1070 | 0 | if(crt + len > end) |
1071 | 0 | goto error_uri; |
1072 | 0 | memcpy(crt, tmp, len); |
1073 | 0 | crt += len; |
1074 | 0 | } |
1075 | | /* headers */ |
1076 | 0 | tmp = uri.headers.s; |
1077 | 0 | if(tmp) { |
1078 | 0 | len = uri.headers.len; |
1079 | 0 | if(crt + len + 1 > end) |
1080 | 0 | goto error_uri; |
1081 | 0 | *crt = '?'; |
1082 | 0 | crt++; |
1083 | 0 | memcpy(crt, tmp, len); |
1084 | 0 | crt += len; |
1085 | 0 | } |
1086 | 0 | done_seturi: |
1087 | 0 | *crt = 0; /* null terminate the thing */ |
1088 | | /* copy it to the msg */ |
1089 | 0 | if(msg->new_uri.s) |
1090 | 0 | pkg_free(msg->new_uri.s); |
1091 | 0 | msg->new_uri.s = new_uri; |
1092 | 0 | msg->new_uri.len = crt - new_uri; |
1093 | 0 | msg->parsed_uri_ok = 0; |
1094 | 0 | ruri_mark_new(); /* available for forking */ |
1095 | 0 | ret = 1; |
1096 | 0 | break; |
1097 | 0 | case IF_T: |
1098 | 0 | rve = (struct rval_expr *)a->val[0].u.data; |
1099 | 0 | if(unlikely(rval_expr_eval_long(h, msg, &v, rve) != 0)) { |
1100 | 0 | ERR("if expression evaluation failed (%d,%d-%d,%d)\n", |
1101 | 0 | rve->fpos.s_line, rve->fpos.s_col, rve->fpos.e_line, |
1102 | 0 | rve->fpos.e_col); |
1103 | 0 | v = 0; /* false */ |
1104 | 0 | } |
1105 | 0 | if(unlikely(h->run_flags & EXIT_R_F)) { |
1106 | 0 | ret = 0; |
1107 | 0 | break; |
1108 | 0 | } |
1109 | 0 | h->run_flags &= ~(RETURN_R_F | BREAK_R_F); /* catch return & |
1110 | | break in expr*/ |
1111 | 0 | ret = 1; /*default is continue */ |
1112 | 0 | if((ksr_return_mode == 0 && v > 0) |
1113 | 0 | || (ksr_return_mode != 0 && v != 0)) { |
1114 | 0 | if((a->val[1].type == ACTIONS_ST) && a->val[1].u.data) { |
1115 | 0 | ret = run_actions( |
1116 | 0 | h, (struct action *)a->val[1].u.data, msg); |
1117 | 0 | } |
1118 | 0 | } else if((a->val[2].type == ACTIONS_ST) && a->val[2].u.data) { |
1119 | 0 | ret = run_actions(h, (struct action *)a->val[2].u.data, msg); |
1120 | 0 | } |
1121 | 0 | break; |
1122 | 0 | case MODULE0_T: |
1123 | 0 | MODF_CALL(cmd_function, h, msg, a->val, 0, 0); |
1124 | 0 | break; |
1125 | | /* instead of using the parameter number, we use different names |
1126 | | * for calls to functions with 3, 4, 5, 6 or variable number of |
1127 | | * parameters due to performance reasons */ |
1128 | 0 | case MODULE1_T: |
1129 | 0 | MODF_CALL( |
1130 | 0 | cmd_function, h, msg, a->val, (char *)a->val[2].u.data, 0); |
1131 | 0 | break; |
1132 | 0 | case MODULE2_T: |
1133 | 0 | MODF_CALL(cmd_function, h, msg, a->val, (char *)a->val[2].u.data, |
1134 | 0 | (char *)a->val[3].u.data); |
1135 | 0 | break; |
1136 | 0 | case MODULE3_T: |
1137 | 0 | MODF_CALL(cmd_function3, h, msg, a->val, (char *)a->val[2].u.data, |
1138 | 0 | (char *)a->val[3].u.data, (char *)a->val[4].u.data); |
1139 | 0 | break; |
1140 | 0 | case MODULE4_T: |
1141 | 0 | MODF_CALL(cmd_function4, h, msg, a->val, (char *)a->val[2].u.data, |
1142 | 0 | (char *)a->val[3].u.data, (char *)a->val[4].u.data, |
1143 | 0 | (char *)a->val[5].u.data); |
1144 | 0 | break; |
1145 | 0 | case MODULE5_T: |
1146 | 0 | MODF_CALL(cmd_function5, h, msg, a->val, (char *)a->val[2].u.data, |
1147 | 0 | (char *)a->val[3].u.data, (char *)a->val[4].u.data, |
1148 | 0 | (char *)a->val[5].u.data, (char *)a->val[6].u.data); |
1149 | 0 | break; |
1150 | 0 | case MODULE6_T: |
1151 | 0 | MODF_CALL(cmd_function6, h, msg, a->val, (char *)a->val[2].u.data, |
1152 | 0 | (char *)a->val[3].u.data, (char *)a->val[4].u.data, |
1153 | 0 | (char *)a->val[5].u.data, (char *)a->val[6].u.data, |
1154 | 0 | (char *)a->val[7].u.data); |
1155 | 0 | break; |
1156 | 0 | case MODULEX_T: |
1157 | 0 | MODF_CALL(cmd_function_var, h, msg, a->val, a->val[1].u.number, |
1158 | 0 | &a->val[2]); |
1159 | 0 | break; |
1160 | 0 | case MODULE1_RVE_T: |
1161 | 0 | MODF_RVE_CALL(cmd_function, h, msg, a->val, mod_f_params, |
1162 | 0 | (char *)mod_f_params[2].u.data, 0); |
1163 | 0 | break; |
1164 | 0 | case MODULE2_RVE_T: |
1165 | 0 | MODF_RVE_CALL(cmd_function, h, msg, a->val, mod_f_params, |
1166 | 0 | (char *)mod_f_params[2].u.data, |
1167 | 0 | (char *)mod_f_params[3].u.data); |
1168 | 0 | break; |
1169 | 0 | case MODULE3_RVE_T: |
1170 | 0 | MODF_RVE_CALL(cmd_function3, h, msg, a->val, mod_f_params, |
1171 | 0 | (char *)mod_f_params[2].u.data, |
1172 | 0 | (char *)mod_f_params[3].u.data, |
1173 | 0 | (char *)mod_f_params[4].u.data); |
1174 | 0 | break; |
1175 | 0 | case MODULE4_RVE_T: |
1176 | 0 | MODF_RVE_CALL(cmd_function4, h, msg, a->val, mod_f_params, |
1177 | 0 | (char *)mod_f_params[2].u.data, |
1178 | 0 | (char *)mod_f_params[3].u.data, |
1179 | 0 | (char *)mod_f_params[4].u.data, |
1180 | 0 | (char *)mod_f_params[5].u.data); |
1181 | 0 | break; |
1182 | 0 | case MODULE5_RVE_T: |
1183 | 0 | MODF_RVE_CALL(cmd_function5, h, msg, a->val, mod_f_params, |
1184 | 0 | (char *)mod_f_params[2].u.data, |
1185 | 0 | (char *)mod_f_params[3].u.data, |
1186 | 0 | (char *)mod_f_params[4].u.data, |
1187 | 0 | (char *)mod_f_params[5].u.data, |
1188 | 0 | (char *)mod_f_params[6].u.data); |
1189 | 0 | break; |
1190 | 0 | case MODULE6_RVE_T: |
1191 | 0 | MODF_RVE_CALL(cmd_function6, h, msg, a->val, mod_f_params, |
1192 | 0 | (char *)mod_f_params[2].u.data, |
1193 | 0 | (char *)mod_f_params[3].u.data, |
1194 | 0 | (char *)mod_f_params[4].u.data, |
1195 | 0 | (char *)mod_f_params[5].u.data, |
1196 | 0 | (char *)mod_f_params[6].u.data, |
1197 | 0 | (char *)mod_f_params[7].u.data); |
1198 | 0 | break; |
1199 | 0 | case MODULEX_RVE_T: |
1200 | 0 | MODF_RVE_CALL(cmd_function_var, h, msg, a->val, mod_f_params, |
1201 | 0 | a->val[1].u.number, &mod_f_params[2]); |
1202 | 0 | break; |
1203 | 0 | case EVAL_T: |
1204 | | /* only eval the expression to account for possible |
1205 | | side-effect */ |
1206 | 0 | rval_expr_eval_long( |
1207 | 0 | h, msg, &v, (struct rval_expr *)a->val[0].u.data); |
1208 | 0 | if(h->run_flags & EXIT_R_F) { |
1209 | 0 | ret = 0; |
1210 | 0 | break; |
1211 | 0 | } |
1212 | 0 | h->run_flags &= ~RETURN_R_F | BREAK_R_F; /* catch return & break in |
1213 | | expr */ |
1214 | 0 | ret = 1; /* default is continue */ |
1215 | 0 | break; |
1216 | 0 | case SWITCH_COND_T: |
1217 | 0 | sct = (struct switch_cond_table *)a->val[1].u.data; |
1218 | 0 | if(unlikely(rval_expr_eval_long(h, msg, &v, |
1219 | 0 | (struct rval_expr *)a->val[0].u.data) |
1220 | 0 | < 0)) { |
1221 | | /* handle error in expression => use default */ |
1222 | 0 | ret = -1; |
1223 | 0 | goto sw_cond_def; |
1224 | 0 | } |
1225 | 0 | if(h->run_flags & EXIT_R_F) { |
1226 | 0 | ret = 0; |
1227 | 0 | break; |
1228 | 0 | } |
1229 | 0 | h->run_flags &= ~(RETURN_R_F | BREAK_R_F); /* catch return & break |
1230 | | in expr */ |
1231 | 0 | ret = 1; /* default is continue */ |
1232 | 0 | for(i = 0; i < sct->n; i++) |
1233 | 0 | if(sct->cond[i] == v) { |
1234 | 0 | if(likely(sct->jump[i])) { |
1235 | 0 | ret = run_actions(h, sct->jump[i], msg); |
1236 | 0 | h->run_flags &= ~BREAK_R_F; /* catch breaks, but let |
1237 | | returns passthrough */ |
1238 | 0 | } |
1239 | 0 | goto skip; |
1240 | 0 | } |
1241 | 0 | sw_cond_def: |
1242 | 0 | if(sct->def) { |
1243 | 0 | ret = run_actions(h, sct->def, msg); |
1244 | 0 | h->run_flags &= ~BREAK_R_F; /* catch breaks, but let |
1245 | | returns passthrough */ |
1246 | 0 | } |
1247 | 0 | break; |
1248 | 0 | case SWITCH_JT_T: |
1249 | 0 | sjt = (struct switch_jmp_table *)a->val[1].u.data; |
1250 | 0 | if(unlikely(rval_expr_eval_long(h, msg, &v, |
1251 | 0 | (struct rval_expr *)a->val[0].u.data) |
1252 | 0 | < 0)) { |
1253 | | /* handle error in expression => use default */ |
1254 | 0 | ret = -1; |
1255 | 0 | goto sw_jt_def; |
1256 | 0 | } |
1257 | 0 | if(h->run_flags & EXIT_R_F) { |
1258 | 0 | ret = 0; |
1259 | 0 | break; |
1260 | 0 | } |
1261 | 0 | h->run_flags &= ~(RETURN_R_F | BREAK_R_F); /* catch return & break |
1262 | | in expr */ |
1263 | 0 | ret = 1; /* default is continue */ |
1264 | 0 | if(likely(v >= sjt->first && v <= sjt->last)) { |
1265 | 0 | if(likely(sjt->tbl[v - sjt->first])) { |
1266 | 0 | ret = run_actions(h, sjt->tbl[v - sjt->first], msg); |
1267 | 0 | h->run_flags &= ~BREAK_R_F; /* catch breaks, but let |
1268 | | returns passthrough */ |
1269 | 0 | } |
1270 | 0 | break; |
1271 | 0 | } else { |
1272 | 0 | for(i = 0; i < sjt->rest.n; i++) |
1273 | 0 | if(sjt->rest.cond[i] == v) { |
1274 | 0 | if(likely(sjt->rest.jump[i])) { |
1275 | 0 | ret = run_actions(h, sjt->rest.jump[i], msg); |
1276 | 0 | h->run_flags &= ~BREAK_R_F; /* catch breaks, but |
1277 | | let returns pass */ |
1278 | 0 | } |
1279 | 0 | goto skip; |
1280 | 0 | } |
1281 | 0 | } |
1282 | | /* not found => try default */ |
1283 | 0 | sw_jt_def: |
1284 | 0 | if(sjt->rest.def) { |
1285 | 0 | ret = run_actions(h, sjt->rest.def, msg); |
1286 | 0 | h->run_flags &= ~BREAK_R_F; /* catch breaks, but let |
1287 | | returns passthrough */ |
1288 | 0 | } |
1289 | 0 | break; |
1290 | 0 | case BLOCK_T: |
1291 | 0 | if(likely(a->val[0].u.data)) { |
1292 | 0 | ret = run_actions(h, (struct action *)a->val[0].u.data, msg); |
1293 | 0 | h->run_flags &= ~BREAK_R_F; /* catch breaks, but let |
1294 | | returns passthrough */ |
1295 | 0 | } |
1296 | 0 | break; |
1297 | 0 | case MATCH_COND_T: |
1298 | 0 | mct = (struct match_cond_table *)a->val[1].u.data; |
1299 | 0 | rval_cache_init(&c1); |
1300 | 0 | rv = 0; |
1301 | 0 | rv1 = 0; |
1302 | 0 | ret = rval_expr_eval_rvlong( |
1303 | 0 | h, msg, &rv, &v, (struct rval_expr *)a->val[0].u.data, &c1); |
1304 | |
|
1305 | 0 | if(unlikely(ret < 0)) { |
1306 | | /* handle error in expression => use default */ |
1307 | 0 | ret = -1; |
1308 | 0 | goto match_cond_def; |
1309 | 0 | } |
1310 | 0 | if(h->run_flags & EXIT_R_F) { |
1311 | 0 | ret = 0; |
1312 | 0 | break; |
1313 | 0 | } |
1314 | 0 | h->run_flags &= ~(RETURN_R_F | BREAK_R_F); /* catch return & break |
1315 | | in expr */ |
1316 | 0 | if(likely(rv)) { |
1317 | 0 | rv1 = rval_convert(h, msg, RV_STR, rv, &c1); |
1318 | 0 | if(unlikely(rv1 == 0)) { |
1319 | 0 | ret = -1; |
1320 | 0 | goto match_cond_def; |
1321 | 0 | } |
1322 | 0 | s = rv1->v.s; |
1323 | 0 | } else { |
1324 | | /* int result in v */ |
1325 | 0 | rval_cache_clean(&c1); |
1326 | 0 | s.s = sint2str(v, &s.len); |
1327 | 0 | } |
1328 | 0 | ret = 1; /* default is continue */ |
1329 | 0 | for(i = 0; i < mct->n; i++) |
1330 | 0 | if((mct->match[i].type == MATCH_STR |
1331 | 0 | && mct->match[i].l.s.len == s.len |
1332 | 0 | && memcmp(mct->match[i].l.s.s, s.s, s.len) == 0) |
1333 | 0 | || (mct->match[i].type == MATCH_RE |
1334 | 0 | && regexec(mct->match[i].l.regex, s.s, 0, 0, 0) |
1335 | 0 | == 0)) { |
1336 | 0 | if(likely(mct->jump[i])) { |
1337 | | /* make sure we cleanup first, in case run_actions() |
1338 | | exits the script directly via longjmp() */ |
1339 | 0 | if(rv1) { |
1340 | 0 | rval_destroy(rv1); |
1341 | 0 | rval_destroy(rv); |
1342 | 0 | rval_cache_clean(&c1); |
1343 | 0 | } else if(rv) { |
1344 | 0 | rval_destroy(rv); |
1345 | 0 | rval_cache_clean(&c1); |
1346 | 0 | } |
1347 | 0 | ret = run_actions(h, mct->jump[i], msg); |
1348 | 0 | h->run_flags &= ~BREAK_R_F; /* catch breaks, but let |
1349 | | returns passthrough */ |
1350 | 0 | goto skip; |
1351 | 0 | } |
1352 | 0 | goto match_cleanup; |
1353 | 0 | } |
1354 | 0 | match_cond_def: |
1355 | 0 | if(mct->def) { |
1356 | | /* make sure we cleanup first, in case run_actions() |
1357 | | exits the script directly via longjmp() */ |
1358 | 0 | if(rv1) { |
1359 | 0 | rval_destroy(rv1); |
1360 | 0 | rval_destroy(rv); |
1361 | 0 | rval_cache_clean(&c1); |
1362 | 0 | } else if(rv) { |
1363 | 0 | rval_destroy(rv); |
1364 | 0 | rval_cache_clean(&c1); |
1365 | 0 | } |
1366 | 0 | ret = run_actions(h, mct->def, msg); |
1367 | 0 | h->run_flags &= ~BREAK_R_F; /* catch breaks, but let |
1368 | | returns passthrough */ |
1369 | 0 | break; |
1370 | 0 | } |
1371 | 0 | match_cleanup: |
1372 | 0 | if(rv1) { |
1373 | 0 | rval_destroy(rv1); |
1374 | 0 | rval_destroy(rv); |
1375 | 0 | rval_cache_clean(&c1); |
1376 | 0 | } else if(rv) { |
1377 | 0 | rval_destroy(rv); |
1378 | 0 | rval_cache_clean(&c1); |
1379 | 0 | } |
1380 | 0 | break; |
1381 | 0 | case WHILE_T: |
1382 | 0 | i = 0; |
1383 | 0 | flags = 0; |
1384 | 0 | rve = (struct rval_expr *)a->val[0].u.data; |
1385 | 0 | ret = 1; |
1386 | 0 | while(!(flags & (BREAK_R_F | RETURN_R_F | EXIT_R_F)) |
1387 | 0 | && (rval_expr_eval_long(h, msg, &v, rve) == 0) |
1388 | 0 | && ((ksr_return_mode == 0 && v > 0) |
1389 | 0 | || (ksr_return_mode != 0 && v != 0))) { |
1390 | 0 | if(cfg_get(core, core_cfg, max_while_loops) > 0) |
1391 | 0 | i++; |
1392 | |
|
1393 | 0 | if(unlikely(i > cfg_get(core, core_cfg, max_while_loops))) { |
1394 | 0 | LM_ERR("runaway while (%d, %d): more than %d loops\n", |
1395 | 0 | rve->fpos.s_line, rve->fpos.s_col, |
1396 | 0 | cfg_get(core, core_cfg, max_while_loops)); |
1397 | 0 | ret = -1; |
1398 | 0 | goto error; |
1399 | 0 | } |
1400 | 0 | if(likely(a->val[1].u.data)) { |
1401 | 0 | ret = run_actions( |
1402 | 0 | h, (struct action *)a->val[1].u.data, msg); |
1403 | 0 | flags |= h->run_flags; |
1404 | 0 | h->run_flags &= ~BREAK_R_F; /* catch breaks, but let |
1405 | | returns pass-through */ |
1406 | 0 | } |
1407 | 0 | } |
1408 | 0 | break; |
1409 | 0 | case FORCE_RPORT_T: |
1410 | 0 | msg->msg_flags |= FL_FORCE_RPORT; |
1411 | 0 | ret = 1; /* continue processing */ |
1412 | 0 | break; |
1413 | 0 | case ADD_LOCAL_RPORT_T: |
1414 | 0 | msg->msg_flags |= FL_ADD_LOCAL_RPORT; |
1415 | 0 | ret = 1; /* continue processing */ |
1416 | 0 | break; |
1417 | 0 | case UDP_MTU_TRY_PROTO_T: |
1418 | 0 | msg->msg_flags |= (msg_flags_t)a->val[0].u.number & FL_MTU_FB_MASK; |
1419 | 0 | ret = 1; /* continue processing */ |
1420 | 0 | break; |
1421 | 0 | case SET_ADV_ADDR_T: |
1422 | 0 | if(a->val[0].type != STR_ST) { |
1423 | 0 | LM_CRIT("bad set_advertised_address() type %d\n", |
1424 | 0 | a->val[0].type); |
1425 | 0 | ret = E_BUG; |
1426 | 0 | goto error; |
1427 | 0 | } |
1428 | 0 | msg->set_global_address = *((str *)a->val[0].u.data); |
1429 | 0 | ret = 1; /* continue processing */ |
1430 | 0 | break; |
1431 | 0 | case SET_ADV_PORT_T: |
1432 | 0 | if(a->val[0].type != STR_ST) { |
1433 | 0 | LM_CRIT("bad set_advertised_port() type %d\n", a->val[0].type); |
1434 | 0 | ret = E_BUG; |
1435 | 0 | goto error; |
1436 | 0 | } |
1437 | 0 | msg->set_global_port = *((str *)a->val[0].u.data); |
1438 | 0 | ret = 1; /* continue processing */ |
1439 | 0 | break; |
1440 | 0 | #ifdef USE_TCP |
1441 | 0 | case FORCE_TCP_ALIAS_T: |
1442 | 0 | if(msg->rcv.proto == PROTO_TCP |
1443 | 0 | #ifdef USE_TLS |
1444 | 0 | || msg->rcv.proto == PROTO_TLS |
1445 | 0 | #endif |
1446 | 0 | ) { |
1447 | |
|
1448 | 0 | if(a->val[0].type == NOSUBTYPE) |
1449 | 0 | port = msg->via1->port; |
1450 | 0 | else if(a->val[0].type == NUMBER_ST) |
1451 | 0 | port = (int)a->val[0].u.number; |
1452 | 0 | else { |
1453 | 0 | LM_CRIT("bad force_tcp_alias" |
1454 | 0 | " port type %d\n", |
1455 | 0 | a->val[0].type); |
1456 | 0 | ret = E_BUG; |
1457 | 0 | goto error; |
1458 | 0 | } |
1459 | | |
1460 | 0 | if(tcpconn_add_alias( |
1461 | 0 | msg->rcv.proto_reserved1, port, msg->rcv.proto) |
1462 | 0 | != 0) { |
1463 | 0 | LM_ERR("receive_msg: tcp alias failed\n"); |
1464 | 0 | ret = E_UNSPEC; |
1465 | 0 | goto error; |
1466 | 0 | } |
1467 | 0 | } |
1468 | 0 | #endif |
1469 | 0 | ret = 1; /* continue processing */ |
1470 | 0 | break; |
1471 | 0 | case FORCE_SEND_SOCKET_T: |
1472 | 0 | if(a->val[0].type != SOCKETINFO_ST) { |
1473 | 0 | LM_CRIT("bad force_send_socket argument" |
1474 | 0 | " type: %d\n", |
1475 | 0 | a->val[0].type); |
1476 | 0 | ret = E_BUG; |
1477 | 0 | goto error; |
1478 | 0 | } |
1479 | 0 | LM_DBG("setting send-socket to [%.*s]\n", |
1480 | 0 | ((struct socket_info *)a->val[0].u.data)->sock_str.len, |
1481 | 0 | ((struct socket_info *)a->val[0].u.data)->sock_str.s); |
1482 | 0 | set_force_socket(msg, (struct socket_info *)a->val[0].u.data); |
1483 | 0 | ret = 1; /* continue processing */ |
1484 | 0 | break; |
1485 | | |
1486 | 0 | case ADD_T: |
1487 | 0 | case ASSIGN_T: |
1488 | 0 | v = lval_assign(h, msg, (struct lvalue *)a->val[0].u.data, |
1489 | 0 | (struct rval_expr *)a->val[1].u.data); |
1490 | 0 | if(likely(v >= 0)) |
1491 | 0 | ret = 1; |
1492 | 0 | else if(unlikely(v == EXPR_DROP)) /* hack to quit on DROP*/ |
1493 | 0 | ret = 0; |
1494 | 0 | else |
1495 | 0 | ret = v; |
1496 | 0 | break; |
1497 | 0 | case SET_FWD_NO_CONNECT_T: |
1498 | 0 | msg->fwd_send_flags.f |= SND_F_FORCE_CON_REUSE; |
1499 | 0 | ret = 1; /* continue processing */ |
1500 | 0 | break; |
1501 | 0 | case SET_RPL_NO_CONNECT_T: |
1502 | 0 | msg->rpl_send_flags.f |= SND_F_FORCE_CON_REUSE; |
1503 | 0 | ret = 1; /* continue processing */ |
1504 | 0 | break; |
1505 | 0 | case SET_FWD_CLOSE_T: |
1506 | 0 | msg->fwd_send_flags.f |= SND_F_CON_CLOSE; |
1507 | 0 | ret = 1; /* continue processing */ |
1508 | 0 | break; |
1509 | 0 | case SET_RPL_CLOSE_T: |
1510 | 0 | msg->rpl_send_flags.f |= SND_F_CON_CLOSE; |
1511 | 0 | ret = 1; /* continue processing */ |
1512 | 0 | break; |
1513 | 0 | case CFG_SELECT_T: |
1514 | 0 | if(a->val[0].type != CFG_GROUP_ST) { |
1515 | 0 | BUG("unsupported parameter in CFG_SELECT_T: %d\n", |
1516 | 0 | a->val[0].type); |
1517 | 0 | ret = -1; |
1518 | 0 | goto error; |
1519 | 0 | } |
1520 | 0 | switch(a->val[1].type) { |
1521 | 0 | case NUMBER_ST: |
1522 | 0 | v = (int)a->val[1].u.number; |
1523 | 0 | break; |
1524 | 0 | case RVE_ST: |
1525 | 0 | if(rval_expr_eval_long( |
1526 | 0 | h, msg, &v, (struct rval_expr *)a->val[1].u.data) |
1527 | 0 | < 0) { |
1528 | 0 | ret = -1; |
1529 | 0 | goto error; |
1530 | 0 | } |
1531 | 0 | break; |
1532 | 0 | default: |
1533 | 0 | BUG("unsupported group id type in CFG_SELECT_T: %d\n", |
1534 | 0 | a->val[1].type); |
1535 | 0 | ret = -1; |
1536 | 0 | goto error; |
1537 | 0 | } |
1538 | 0 | ret = (cfg_select((cfg_group_t *)a->val[0].u.data, v) == 0) ? 1 |
1539 | 0 | : -1; |
1540 | 0 | break; |
1541 | 0 | case CFG_RESET_T: |
1542 | 0 | if(a->val[0].type != CFG_GROUP_ST) { |
1543 | 0 | BUG("unsupported parameter in CFG_RESET_T: %d\n", |
1544 | 0 | a->val[0].type); |
1545 | 0 | ret = -1; |
1546 | 0 | goto error; |
1547 | 0 | } |
1548 | 0 | ret = (cfg_reset((cfg_group_t *)a->val[0].u.data) == 0) ? 1 : -1; |
1549 | 0 | break; |
1550 | | /* |
1551 | | default: |
1552 | | LM_CRIT("unknown type %d\n", a->type); |
1553 | | */ |
1554 | 0 | } |
1555 | 0 | skip: |
1556 | 0 | return ret; |
1557 | | |
1558 | 0 | error_uri: |
1559 | 0 | LM_ERR("set*: uri too long\n"); |
1560 | 0 | if(new_uri) |
1561 | 0 | pkg_free(new_uri); |
1562 | 0 | LM_ERR("run action error at: %s:%d\n", (a->cfile) ? a->cfile : "", |
1563 | 0 | a->cline); |
1564 | 0 | return E_UNSPEC; |
1565 | 0 | error_fwd_uri: |
1566 | | /*free_uri(&uri); -- not needed anymore, using msg->parsed_uri*/ |
1567 | 0 | error: |
1568 | 0 | LM_ERR("run action error at: %s:%d\n", (a->cfile) ? a->cfile : "", |
1569 | 0 | a->cline); |
1570 | 0 | return ret; |
1571 | 0 | } |
1572 | | |
1573 | | |
1574 | | /* returns: 0, or 1 on success, <0 on error */ |
1575 | | /* (0 if drop or break encountered, 1 if not ) */ |
1576 | | int run_actions(struct run_act_ctx *h, struct action *a, struct sip_msg *msg) |
1577 | 0 | { |
1578 | 0 | struct action *t; |
1579 | 0 | int ret; |
1580 | 0 | struct timeval tvb = {0}, tve = {0}; |
1581 | 0 | struct timezone tz; |
1582 | 0 | unsigned int tdiff; |
1583 | |
|
1584 | 0 | ret = E_UNSPEC; |
1585 | 0 | h->rec_lev++; |
1586 | 0 | if(unlikely(h->rec_lev > max_recursive_level)) { |
1587 | 0 | LM_ERR("too many recursive routing table lookups (%d) giving up!\n", |
1588 | 0 | h->rec_lev); |
1589 | 0 | ret = E_UNSPEC; |
1590 | 0 | goto error; |
1591 | 0 | } |
1592 | 0 | if(unlikely(h->rec_lev == 1)) { |
1593 | 0 | h->run_flags = 0; |
1594 | 0 | h->last_retcode = 0; |
1595 | 0 | _last_returned_code = h->last_retcode; |
1596 | 0 | #ifdef USE_LONGJMP |
1597 | 0 | if(unlikely(setjmp(h->jmp_env))) { |
1598 | 0 | h->rec_lev = 0; |
1599 | 0 | ret = h->last_retcode; |
1600 | 0 | goto end; |
1601 | 0 | } |
1602 | 0 | #endif |
1603 | 0 | } |
1604 | | |
1605 | 0 | if(unlikely(a == 0)) { |
1606 | 0 | LM_DBG("null action list (rec_level=%d)\n", h->rec_lev); |
1607 | 0 | ret = 1; |
1608 | 0 | } |
1609 | |
|
1610 | 0 | for(t = a; t != 0; t = t->next) { |
1611 | |
|
1612 | 0 | if(unlikely(cfg_get(core, core_cfg, latency_limit_action) > 0) |
1613 | 0 | && is_printable(cfg_get(core, core_cfg, latency_log))) { |
1614 | 0 | gettimeofday(&tvb, &tz); |
1615 | 0 | } |
1616 | 0 | _cfg_crt_action = t; |
1617 | 0 | if(unlikely(log_prefix_mode == 1)) { |
1618 | 0 | log_prefix_set(msg); |
1619 | 0 | } |
1620 | 0 | ret = do_action(h, t, msg); |
1621 | 0 | _cfg_crt_action = 0; |
1622 | 0 | if(unlikely(log_prefix_mode == 1)) { |
1623 | 0 | log_prefix_set(msg); |
1624 | 0 | } |
1625 | 0 | if(unlikely(cfg_get(core, core_cfg, latency_limit_action) > 0) |
1626 | 0 | && is_printable(cfg_get(core, core_cfg, latency_log))) { |
1627 | 0 | gettimeofday(&tve, &tz); |
1628 | 0 | tdiff = (tve.tv_sec - tvb.tv_sec) * 1000000 |
1629 | 0 | + (tve.tv_usec - tvb.tv_usec); |
1630 | 0 | if(tdiff >= cfg_get(core, core_cfg, latency_limit_action)) { |
1631 | 0 | LOG(cfg_get(core, core_cfg, latency_log), |
1632 | 0 | "alert - action [%s (%d)]" |
1633 | 0 | " cfg [%s:%d] took too long [%u us]\n", |
1634 | 0 | is_mod_func(t) |
1635 | 0 | ? ((cmd_export_t *)(t->val[0].u.data))->name |
1636 | 0 | : "corefunc", |
1637 | 0 | t->type, (t->cfile) ? t->cfile : "", t->cline, tdiff); |
1638 | 0 | } |
1639 | 0 | } |
1640 | | /* break, return or drop/exit stop execution of the current |
1641 | | block */ |
1642 | 0 | if(unlikely(h->run_flags & (BREAK_R_F | RETURN_R_F | EXIT_R_F))) { |
1643 | 0 | if(unlikely(h->run_flags & EXIT_R_F)) { |
1644 | 0 | h->last_retcode = ret; |
1645 | 0 | _last_returned_code = h->last_retcode; |
1646 | 0 | #ifdef USE_LONGJMP |
1647 | 0 | longjmp(h->jmp_env, ret); |
1648 | 0 | #endif |
1649 | 0 | } |
1650 | 0 | break; |
1651 | 0 | } |
1652 | | /* ignore error returns */ |
1653 | 0 | } |
1654 | | |
1655 | 0 | h->rec_lev--; |
1656 | 0 | end: |
1657 | 0 | return ret; |
1658 | | |
1659 | | |
1660 | 0 | error: |
1661 | 0 | h->rec_lev--; |
1662 | 0 | return ret; |
1663 | 0 | } |
1664 | | |
1665 | | |
1666 | | #ifdef USE_LONGJMP |
1667 | | /** safe version of run_actions(). |
1668 | | * It always return (it doesn't longjmp on forced script end). |
1669 | | * @returns 0, or 1 on success, <0 on error |
1670 | | * (0 if drop or break encountered, 1 if not ) */ |
1671 | | int run_actions_safe( |
1672 | | struct run_act_ctx *h, struct action *a, struct sip_msg *msg) |
1673 | 0 | { |
1674 | 0 | struct run_act_ctx ctx; |
1675 | 0 | int ret; |
1676 | 0 | int ign_on_break; |
1677 | | |
1678 | | /* start with a fresh action context */ |
1679 | 0 | init_run_actions_ctx(&ctx); |
1680 | 0 | ctx.last_retcode = h->last_retcode; |
1681 | 0 | ign_on_break = h->run_flags & IGNORE_ON_BREAK_R_F; |
1682 | 0 | ctx.run_flags = h->run_flags | IGNORE_ON_BREAK_R_F; |
1683 | 0 | ret = run_actions(&ctx, a, msg); |
1684 | 0 | h->last_retcode = ctx.last_retcode; |
1685 | 0 | h->run_flags = (ctx.run_flags & ~IGNORE_ON_BREAK_R_F) | ign_on_break; |
1686 | 0 | return ret; |
1687 | 0 | } |
1688 | | #endif /* USE_LONGJMP */ |
1689 | | |
1690 | | |
1691 | | int run_top_route(struct action *a, sip_msg_t *msg, struct run_act_ctx *c) |
1692 | 0 | { |
1693 | 0 | struct run_act_ctx ctx; |
1694 | 0 | struct run_act_ctx *p; |
1695 | 0 | int ret; |
1696 | 0 | flag_t sfbk; |
1697 | |
|
1698 | 0 | p = (c) ? c : &ctx; |
1699 | 0 | sfbk = getsflags(); |
1700 | 0 | setsflagsval(0); |
1701 | 0 | reset_static_buffer(); |
1702 | 0 | init_run_actions_ctx(p); |
1703 | 0 | ret = run_actions(p, a, msg); |
1704 | 0 | setsflagsval(sfbk); |
1705 | 0 | return ret; |
1706 | 0 | } |
1707 | | |
1708 | | |
1709 | | /** |
1710 | | * |
1711 | | */ |
1712 | | int run_child_one_init_route(void) |
1713 | 0 | { |
1714 | 0 | struct sip_msg *fmsg; |
1715 | 0 | run_act_ctx_t ctx; |
1716 | 0 | run_act_ctx_t *bctx; |
1717 | 0 | int rtb, rt; |
1718 | 0 | sr_kemi_eng_t *keng = NULL; |
1719 | 0 | str evname = str_init("core:worker-one-init"); |
1720 | |
|
1721 | 0 | LM_DBG("attempting to run event_route[%s]\n", evname.s); |
1722 | |
|
1723 | 0 | if(kemi_event_route_callback.s != NULL |
1724 | 0 | && kemi_event_route_callback.len > 0) { |
1725 | 0 | keng = sr_kemi_eng_get(); |
1726 | 0 | rt = -1; |
1727 | 0 | } else { |
1728 | 0 | rt = route_get(&event_rt, evname.s); |
1729 | 0 | } |
1730 | 0 | if((keng != NULL) || (rt >= 0 && event_rt.rlist[rt] != NULL)) { |
1731 | 0 | if(cfg_child_init()) { |
1732 | 0 | return -1; |
1733 | 0 | } |
1734 | 0 | LM_DBG("executing event_route[%s] (%d)\n", evname.s, rt); |
1735 | 0 | if(faked_msg_init() < 0) |
1736 | 0 | return -1; |
1737 | 0 | fmsg = faked_msg_next(); |
1738 | 0 | rtb = get_route_type(); |
1739 | 0 | set_route_type(REQUEST_ROUTE); |
1740 | 0 | init_run_actions_ctx(&ctx); |
1741 | 0 | if(keng == NULL) { |
1742 | 0 | run_top_route(event_rt.rlist[rt], fmsg, &ctx); |
1743 | 0 | } else { |
1744 | 0 | bctx = sr_kemi_act_ctx_get(); |
1745 | 0 | sr_kemi_act_ctx_set(&ctx); |
1746 | 0 | if(sr_kemi_route(keng, fmsg, EVENT_ROUTE, |
1747 | 0 | &kemi_event_route_callback, &evname) |
1748 | 0 | < 0) { |
1749 | 0 | LM_ERR("error running event route kemi callback\n"); |
1750 | 0 | return -1; |
1751 | 0 | } |
1752 | 0 | sr_kemi_act_ctx_set(bctx); |
1753 | 0 | } |
1754 | 0 | if(ctx.run_flags & DROP_R_F) { |
1755 | 0 | LM_ERR("exit due to 'drop' in event route\n"); |
1756 | 0 | return -1; |
1757 | 0 | } |
1758 | 0 | set_route_type(rtb); |
1759 | 0 | } |
1760 | | |
1761 | 0 | return 0; |
1762 | 0 | } |